add subtitle to the media item
PiperOrigin-RevId: 303753642
This commit is contained in:
parent
0782c5f247
commit
315ba6f324
@ -33,7 +33,6 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer2.Format;
|
|
||||||
import com.google.android.exoplayer2.MediaItem;
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
import com.google.android.exoplayer2.PlaybackPreparer;
|
import com.google.android.exoplayer2.PlaybackPreparer;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
@ -47,8 +46,6 @@ import com.google.android.exoplayer2.offline.DownloadRequest;
|
|||||||
import com.google.android.exoplayer2.source.BehindLiveWindowException;
|
import com.google.android.exoplayer2.source.BehindLiveWindowException;
|
||||||
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
|
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.source.MergingMediaSource;
|
|
||||||
import com.google.android.exoplayer2.source.SingleSampleMediaSource;
|
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
|
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
|
||||||
@ -412,44 +409,25 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
: new UriSample[] {(UriSample) intentAsSample};
|
: new UriSample[] {(UriSample) intentAsSample};
|
||||||
|
|
||||||
boolean seenAdsTagUri = false;
|
boolean seenAdsTagUri = false;
|
||||||
|
List<MediaSource> mediaSources = new ArrayList<>();
|
||||||
for (UriSample sample : samples) {
|
for (UriSample sample : samples) {
|
||||||
seenAdsTagUri |= sample.adTagUri != null;
|
seenAdsTagUri |= sample.adTagUri != null;
|
||||||
if (!Util.checkCleartextTrafficPermitted(sample.uri)) {
|
if (!Util.checkCleartextTrafficPermitted(sample.uri)) {
|
||||||
showToast(R.string.error_cleartext_not_permitted);
|
showToast(R.string.error_cleartext_not_permitted);
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
if (Util.maybeRequestReadExternalStoragePermission(/* activity= */ this, sample.uri)) {
|
if (Util.maybeRequestReadExternalStoragePermission(/* activity= */ this, sample.uri)
|
||||||
|
|| (sample.subtitleInfo != null
|
||||||
|
&& Util.maybeRequestReadExternalStoragePermission(
|
||||||
|
/* activity= */ this, sample.subtitleInfo.uri))) {
|
||||||
// The player will be reinitialized if the permission is granted.
|
// The player will be reinitialized if the permission is granted.
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
List<MediaSource> mediaSources = new ArrayList<>();
|
|
||||||
for (UriSample sample : samples) {
|
|
||||||
MediaSource mediaSource = createLeafMediaSource(sample);
|
MediaSource mediaSource = createLeafMediaSource(sample);
|
||||||
if (mediaSource == null) {
|
if (mediaSource != null) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Sample.SubtitleInfo subtitleInfo = sample.subtitleInfo;
|
|
||||||
if (subtitleInfo != null) {
|
|
||||||
if (Util.maybeRequestReadExternalStoragePermission(
|
|
||||||
/* activity= */ this, subtitleInfo.uri)) {
|
|
||||||
// The player will be reinitialized if the permission is granted.
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
Format subtitleFormat =
|
|
||||||
new Format.Builder()
|
|
||||||
.setSampleMimeType(subtitleInfo.mimeType)
|
|
||||||
.setSelectionFlags(C.SELECTION_FLAG_DEFAULT)
|
|
||||||
.setLanguage(subtitleInfo.language)
|
|
||||||
.build();
|
|
||||||
MediaSource subtitleMediaSource =
|
|
||||||
new SingleSampleMediaSource.Factory(dataSourceFactory)
|
|
||||||
.createMediaSource(subtitleInfo.uri, subtitleFormat, C.TIME_UNSET);
|
|
||||||
mediaSource = new MergingMediaSource(mediaSource, subtitleMediaSource);
|
|
||||||
}
|
|
||||||
mediaSources.add(mediaSource);
|
mediaSources.add(mediaSource);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (seenAdsTagUri && mediaSources.size() == 1) {
|
if (seenAdsTagUri && mediaSources.size() == 1) {
|
||||||
Uri adTagUri = samples[0].adTagUri;
|
Uri adTagUri = samples[0].adTagUri;
|
||||||
if (!adTagUri.equals(loadedAdTagUri)) {
|
if (!adTagUri.equals(loadedAdTagUri)) {
|
||||||
@ -497,6 +475,15 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
drmSessionForClearTypes = parameters.drmInfo.drmSessionForClearTypes;
|
drmSessionForClearTypes = parameters.drmInfo.drmSessionForClearTypes;
|
||||||
drmDataSourceFactory = ((DemoApplication) getApplication()).buildHttpDataSourceFactory();
|
drmDataSourceFactory = ((DemoApplication) getApplication()).buildHttpDataSourceFactory();
|
||||||
}
|
}
|
||||||
|
if (parameters.subtitleInfo != null) {
|
||||||
|
builder.setSubtitles(
|
||||||
|
Collections.singletonList(
|
||||||
|
new MediaItem.Subtitle(
|
||||||
|
parameters.subtitleInfo.uri,
|
||||||
|
parameters.subtitleInfo.mimeType,
|
||||||
|
parameters.subtitleInfo.language,
|
||||||
|
C.SELECTION_FLAG_DEFAULT)));
|
||||||
|
}
|
||||||
|
|
||||||
DownloadRequest downloadRequest =
|
DownloadRequest downloadRequest =
|
||||||
((DemoApplication) getApplication())
|
((DemoApplication) getApplication())
|
||||||
@ -531,7 +518,7 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
debugViewHelper = null;
|
debugViewHelper = null;
|
||||||
player.release();
|
player.release();
|
||||||
player = null;
|
player = null;
|
||||||
mediaSources = null;
|
mediaSources = Collections.emptyList();
|
||||||
trackSelector = null;
|
trackSelector = null;
|
||||||
}
|
}
|
||||||
if (adsLoader != null) {
|
if (adsLoader != null) {
|
||||||
|
@ -61,12 +61,14 @@ public final class MediaItem {
|
|||||||
@Nullable private UUID drmUuid;
|
@Nullable private UUID drmUuid;
|
||||||
private boolean drmMultiSession;
|
private boolean drmMultiSession;
|
||||||
private List<StreamKey> streamKeys;
|
private List<StreamKey> streamKeys;
|
||||||
|
private List<Subtitle> subtitles;
|
||||||
@Nullable private Object tag;
|
@Nullable private Object tag;
|
||||||
@Nullable private MediaMetadata mediaMetadata;
|
@Nullable private MediaMetadata mediaMetadata;
|
||||||
|
|
||||||
/** Creates a builder. */
|
/** Creates a builder. */
|
||||||
public Builder() {
|
public Builder() {
|
||||||
streamKeys = Collections.emptyList();
|
streamKeys = Collections.emptyList();
|
||||||
|
subtitles = Collections.emptyList();
|
||||||
drmLicenseRequestHeaders = Collections.emptyMap();
|
drmLicenseRequestHeaders = Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +140,8 @@ public final class MediaItem {
|
|||||||
/**
|
/**
|
||||||
* Sets the optional request headers attached to the drm license request.
|
* Sets the optional request headers attached to the drm license request.
|
||||||
*
|
*
|
||||||
|
* <p>{@code null} or an empty {@link Map} can be used for a reset.
|
||||||
|
*
|
||||||
* <p>If no valid drm configuration is specified, the drm license request headers are ignored.
|
* <p>If no valid drm configuration is specified, the drm license request headers are ignored.
|
||||||
*/
|
*/
|
||||||
public Builder setDrmLicenseRequestHeaders(
|
public Builder setDrmLicenseRequestHeaders(
|
||||||
@ -176,6 +180,8 @@ public final class MediaItem {
|
|||||||
* Sets the optional stream keys by which the manifest is filtered (only used for adaptive
|
* Sets the optional stream keys by which the manifest is filtered (only used for adaptive
|
||||||
* streams).
|
* streams).
|
||||||
*
|
*
|
||||||
|
* <p>{@code null} or an empty {@link List} can be used for a reset.
|
||||||
|
*
|
||||||
* <p>If a {@link PlaybackProperties#sourceUri} is set, the stream keys are used to create a
|
* <p>If a {@link PlaybackProperties#sourceUri} is set, the stream keys are used to create a
|
||||||
* {@link PlaybackProperties} object. Otherwise it will be ignored.
|
* {@link PlaybackProperties} object. Otherwise it will be ignored.
|
||||||
*/
|
*/
|
||||||
@ -187,6 +193,22 @@ public final class MediaItem {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the optional subtitles.
|
||||||
|
*
|
||||||
|
* <p>{@code null} or an empty {@link List} can be used for a reset.
|
||||||
|
*
|
||||||
|
* <p>If a {@link PlaybackProperties#sourceUri} is set, the subtitles are used to create a
|
||||||
|
* {@link PlaybackProperties} object. Otherwise it will be ignored.
|
||||||
|
*/
|
||||||
|
public Builder setSubtitles(@Nullable List<Subtitle> subtitles) {
|
||||||
|
this.subtitles =
|
||||||
|
subtitles != null && !subtitles.isEmpty()
|
||||||
|
? Collections.unmodifiableList(new ArrayList<>(subtitles))
|
||||||
|
: Collections.emptyList();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the optional tag for custom attributes. The tag for the media source which will be
|
* Sets the optional tag for custom attributes. The tag for the media source which will be
|
||||||
* published in the {@link com.google.android.exoplayer2.Timeline} of the source as {@link
|
* published in the {@link com.google.android.exoplayer2.Timeline} of the source as {@link
|
||||||
@ -222,6 +244,7 @@ public final class MediaItem {
|
|||||||
drmUuid, drmLicenseUri, drmLicenseRequestHeaders, drmMultiSession)
|
drmUuid, drmLicenseUri, drmLicenseRequestHeaders, drmMultiSession)
|
||||||
: null,
|
: null,
|
||||||
streamKeys,
|
streamKeys,
|
||||||
|
subtitles,
|
||||||
tag);
|
tag);
|
||||||
mediaId = mediaId != null ? mediaId : sourceUri.toString();
|
mediaId = mediaId != null ? mediaId : sourceUri.toString();
|
||||||
}
|
}
|
||||||
@ -266,7 +289,7 @@ public final class MediaItem {
|
|||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (obj == null || getClass() != obj.getClass()) {
|
if (!(obj instanceof DrmConfiguration)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,6 +330,9 @@ public final class MediaItem {
|
|||||||
/** Optional stream keys by which the manifest is filtered. */
|
/** Optional stream keys by which the manifest is filtered. */
|
||||||
public final List<StreamKey> streamKeys;
|
public final List<StreamKey> streamKeys;
|
||||||
|
|
||||||
|
/** Optional subtitles to be sideloaded. */
|
||||||
|
public final List<Subtitle> subtitles;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional tag for custom attributes. The tag for the media source which will be published in
|
* Optional tag for custom attributes. The tag for the media source which will be published in
|
||||||
* the {@link com.google.android.exoplayer2.Timeline} of the source as {@link
|
* the {@link com.google.android.exoplayer2.Timeline} of the source as {@link
|
||||||
@ -319,11 +345,13 @@ public final class MediaItem {
|
|||||||
@Nullable String mimeType,
|
@Nullable String mimeType,
|
||||||
@Nullable DrmConfiguration drmConfiguration,
|
@Nullable DrmConfiguration drmConfiguration,
|
||||||
List<StreamKey> streamKeys,
|
List<StreamKey> streamKeys,
|
||||||
|
List<Subtitle> subtitles,
|
||||||
@Nullable Object tag) {
|
@Nullable Object tag) {
|
||||||
this.sourceUri = sourceUri;
|
this.sourceUri = sourceUri;
|
||||||
this.mimeType = mimeType;
|
this.mimeType = mimeType;
|
||||||
this.drmConfiguration = drmConfiguration;
|
this.drmConfiguration = drmConfiguration;
|
||||||
this.streamKeys = streamKeys;
|
this.streamKeys = streamKeys;
|
||||||
|
this.subtitles = subtitles;
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,7 +360,7 @@ public final class MediaItem {
|
|||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (obj == null || getClass() != obj.getClass()) {
|
if (!(obj instanceof PlaybackProperties)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PlaybackProperties other = (PlaybackProperties) obj;
|
PlaybackProperties other = (PlaybackProperties) obj;
|
||||||
@ -340,7 +368,8 @@ public final class MediaItem {
|
|||||||
return sourceUri.equals(other.sourceUri)
|
return sourceUri.equals(other.sourceUri)
|
||||||
&& Util.areEqual(mimeType, other.mimeType)
|
&& Util.areEqual(mimeType, other.mimeType)
|
||||||
&& Util.areEqual(drmConfiguration, other.drmConfiguration)
|
&& Util.areEqual(drmConfiguration, other.drmConfiguration)
|
||||||
&& Util.areEqual(streamKeys, other.streamKeys)
|
&& streamKeys.equals(other.streamKeys)
|
||||||
|
&& subtitles.equals(other.subtitles)
|
||||||
&& Util.areEqual(tag, other.tag);
|
&& Util.areEqual(tag, other.tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,11 +379,78 @@ public final class MediaItem {
|
|||||||
result = 31 * result + (mimeType == null ? 0 : mimeType.hashCode());
|
result = 31 * result + (mimeType == null ? 0 : mimeType.hashCode());
|
||||||
result = 31 * result + (drmConfiguration == null ? 0 : drmConfiguration.hashCode());
|
result = 31 * result + (drmConfiguration == null ? 0 : drmConfiguration.hashCode());
|
||||||
result = 31 * result + streamKeys.hashCode();
|
result = 31 * result + streamKeys.hashCode();
|
||||||
|
result = 31 * result + subtitles.hashCode();
|
||||||
result = 31 * result + (tag == null ? 0 : tag.hashCode());
|
result = 31 * result + (tag == null ? 0 : tag.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Properties for a text track. */
|
||||||
|
public static final class Subtitle {
|
||||||
|
|
||||||
|
/** The {@link Uri} to the subtitle file. */
|
||||||
|
public final Uri uri;
|
||||||
|
/** The MIME type. */
|
||||||
|
public final String mimeType;
|
||||||
|
/** The language. */
|
||||||
|
@Nullable public final String language;
|
||||||
|
/** The selection flags. */
|
||||||
|
@C.SelectionFlags public final int selectionFlags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance.
|
||||||
|
*
|
||||||
|
* @param uri The {@link Uri uri} to the subtitle file.
|
||||||
|
* @param mimeType The mime type.
|
||||||
|
* @param language The optional language.
|
||||||
|
*/
|
||||||
|
public Subtitle(Uri uri, String mimeType, @Nullable String language) {
|
||||||
|
this(uri, mimeType, language, /* selectionFlags= */ 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance with the given selection flags.
|
||||||
|
*
|
||||||
|
* @param uri The {@link Uri uri} to the subtitle file.
|
||||||
|
* @param mimeType The mime type.
|
||||||
|
* @param language The optional language.
|
||||||
|
* @param selectionFlags The selection flags.
|
||||||
|
*/
|
||||||
|
public Subtitle(
|
||||||
|
Uri uri, String mimeType, @Nullable String language, @C.SelectionFlags int selectionFlags) {
|
||||||
|
this.uri = uri;
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
this.language = language;
|
||||||
|
this.selectionFlags = selectionFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(obj instanceof Subtitle)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subtitle other = (Subtitle) obj;
|
||||||
|
|
||||||
|
return uri.equals(other.uri)
|
||||||
|
&& mimeType.equals(other.mimeType)
|
||||||
|
&& Util.areEqual(language, other.language)
|
||||||
|
&& selectionFlags == other.selectionFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = uri.hashCode();
|
||||||
|
result = 31 * result + mimeType.hashCode();
|
||||||
|
result = 31 * result + (language == null ? 0 : language.hashCode());
|
||||||
|
result = 31 * result + selectionFlags;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Identifies the media item. */
|
/** Identifies the media item. */
|
||||||
public final String mediaId;
|
public final String mediaId;
|
||||||
|
|
||||||
@ -374,15 +470,15 @@ public final class MediaItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object o) {
|
public boolean equals(@Nullable Object obj) {
|
||||||
if (this == o) {
|
if (this == obj) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (o == null || getClass() != o.getClass()) {
|
if (!(obj instanceof MediaItem)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaItem other = (MediaItem) o;
|
MediaItem other = (MediaItem) obj;
|
||||||
|
|
||||||
return Util.areEqual(mediaId, other.mediaId)
|
return Util.areEqual(mediaId, other.mediaId)
|
||||||
&& Util.areEqual(playbackProperties, other.playbackProperties)
|
&& Util.areEqual(playbackProperties, other.playbackProperties)
|
||||||
|
@ -21,6 +21,7 @@ import android.util.SparseArray;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
||||||
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.MediaItem;
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
|
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
|
||||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||||
@ -122,6 +123,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
|
|||||||
return new DefaultMediaSourceFactory(context, dataSourceFactory);
|
return new DefaultMediaSourceFactory(context, dataSourceFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final DataSource.Factory dataSourceFactory;
|
||||||
private final SparseArray<MediaSourceFactory> mediaSourceFactories;
|
private final SparseArray<MediaSourceFactory> mediaSourceFactories;
|
||||||
@C.ContentType private final int[] supportedTypes;
|
@C.ContentType private final int[] supportedTypes;
|
||||||
private final String userAgent;
|
private final String userAgent;
|
||||||
@ -133,6 +135,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
|
|||||||
@Nullable private List<StreamKey> streamKeys;
|
@Nullable private List<StreamKey> streamKeys;
|
||||||
|
|
||||||
private DefaultMediaSourceFactory(Context context, DataSource.Factory dataSourceFactory) {
|
private DefaultMediaSourceFactory(Context context, DataSource.Factory dataSourceFactory) {
|
||||||
|
this.dataSourceFactory = dataSourceFactory;
|
||||||
drmSessionManager = DrmSessionManager.getDummyDrmSessionManager();
|
drmSessionManager = DrmSessionManager.getDummyDrmSessionManager();
|
||||||
userAgent = Util.getUserAgent(context, ExoPlayerLibraryInfo.VERSION_SLASHY);
|
userAgent = Util.getUserAgent(context, ExoPlayerLibraryInfo.VERSION_SLASHY);
|
||||||
drmHttpDataSourceFactory = new DefaultHttpDataSourceFactory(userAgent);
|
drmHttpDataSourceFactory = new DefaultHttpDataSourceFactory(userAgent);
|
||||||
@ -244,7 +247,30 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
|
|||||||
!mediaItem.playbackProperties.streamKeys.isEmpty()
|
!mediaItem.playbackProperties.streamKeys.isEmpty()
|
||||||
? mediaItem.playbackProperties.streamKeys
|
? mediaItem.playbackProperties.streamKeys
|
||||||
: streamKeys);
|
: streamKeys);
|
||||||
return mediaSourceFactory.createMediaSource(mediaItem);
|
|
||||||
|
MediaSource leafMediaSource = mediaSourceFactory.createMediaSource(mediaItem);
|
||||||
|
|
||||||
|
if (mediaItem.playbackProperties.subtitles.isEmpty()) {
|
||||||
|
return leafMediaSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MediaItem.Subtitle> subtitles = mediaItem.playbackProperties.subtitles;
|
||||||
|
MediaSource[] mediaSources = new MediaSource[subtitles.size() + 1];
|
||||||
|
mediaSources[0] = leafMediaSource;
|
||||||
|
SingleSampleMediaSource.Factory singleSampleSourceFactory =
|
||||||
|
new SingleSampleMediaSource.Factory(dataSourceFactory);
|
||||||
|
for (int i = 0; i < subtitles.size(); i++) {
|
||||||
|
MediaItem.Subtitle subtitle = subtitles.get(i);
|
||||||
|
Format subtitleFormat =
|
||||||
|
new Format.Builder()
|
||||||
|
.setSampleMimeType(subtitle.mimeType)
|
||||||
|
.setLanguage(subtitle.language)
|
||||||
|
.setSelectionFlags(subtitle.selectionFlags)
|
||||||
|
.build();
|
||||||
|
mediaSources[i + 1] =
|
||||||
|
singleSampleSourceFactory.createMediaSource(subtitle.uri, subtitleFormat, C.TIME_UNSET);
|
||||||
|
}
|
||||||
|
return new MergingMediaSource(mediaSources);
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal methods
|
// internal methods
|
||||||
|
@ -23,6 +23,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|||||||
import com.google.android.exoplayer2.offline.StreamKey;
|
import com.google.android.exoplayer2.offline.StreamKey;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -130,6 +131,24 @@ public class MediaItemTest {
|
|||||||
assertThat(mediaItem.playbackProperties.streamKeys).isEqualTo(streamKeys);
|
assertThat(mediaItem.playbackProperties.streamKeys).isEqualTo(streamKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void builderSetSubtitles_setsSubtitles() {
|
||||||
|
List<MediaItem.Subtitle> subtitles =
|
||||||
|
Arrays.asList(
|
||||||
|
new MediaItem.Subtitle(
|
||||||
|
Uri.parse(URI_STRING + "/en"), MimeTypes.APPLICATION_TTML, /* language= */ "en"),
|
||||||
|
new MediaItem.Subtitle(
|
||||||
|
Uri.parse(URI_STRING + "/de"),
|
||||||
|
MimeTypes.APPLICATION_TTML,
|
||||||
|
/* language= */ null,
|
||||||
|
C.SELECTION_FLAG_DEFAULT));
|
||||||
|
|
||||||
|
MediaItem mediaItem =
|
||||||
|
new MediaItem.Builder().setSourceUri(URI_STRING).setSubtitles(subtitles).build();
|
||||||
|
|
||||||
|
assertThat(mediaItem.playbackProperties.subtitles).isEqualTo(subtitles);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void builderSetTag_isNullByDefault() {
|
public void builderSetTag_isNullByDefault() {
|
||||||
MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_STRING).build();
|
MediaItem mediaItem = new MediaItem.Builder().setSourceUri(URI_STRING).build();
|
||||||
|
@ -17,10 +17,15 @@ package com.google.android.exoplayer2.source;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.MediaItem;
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
@ -29,6 +34,7 @@ import org.junit.runner.RunWith;
|
|||||||
public final class DefaultMediaSourceFactoryTest {
|
public final class DefaultMediaSourceFactoryTest {
|
||||||
|
|
||||||
private static final String URI_MEDIA = "http://exoplayer.dev/video";
|
private static final String URI_MEDIA = "http://exoplayer.dev/video";
|
||||||
|
private static final String URI_TEXT = "http://exoplayer.dev/text";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createMediaSource_withoutMimeType_progressiveSource() {
|
public void createMediaSource_withoutMimeType_progressiveSource() {
|
||||||
@ -80,6 +86,42 @@ public final class DefaultMediaSourceFactoryTest {
|
|||||||
assertThat(mediaSource).isNotNull();
|
assertThat(mediaSource).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createMediaSource_withSubtitle_isMergingMediaSource() {
|
||||||
|
DefaultMediaSourceFactory defaultMediaSourceFactory =
|
||||||
|
DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext());
|
||||||
|
List<MediaItem.Subtitle> subtitles =
|
||||||
|
Arrays.asList(
|
||||||
|
new MediaItem.Subtitle(Uri.parse(URI_TEXT), MimeTypes.APPLICATION_TTML, "en"),
|
||||||
|
new MediaItem.Subtitle(
|
||||||
|
Uri.parse(URI_TEXT), MimeTypes.APPLICATION_TTML, "de", C.SELECTION_FLAG_DEFAULT));
|
||||||
|
MediaItem mediaItem =
|
||||||
|
new MediaItem.Builder().setSourceUri(URI_MEDIA).setSubtitles(subtitles).build();
|
||||||
|
|
||||||
|
MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem);
|
||||||
|
|
||||||
|
assertThat(mediaSource).isInstanceOf(MergingMediaSource.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createMediaSource_withSubtitle_hasTag() {
|
||||||
|
DefaultMediaSourceFactory defaultMediaSourceFactory =
|
||||||
|
DefaultMediaSourceFactory.newInstance(ApplicationProvider.getApplicationContext());
|
||||||
|
Object tag = new Object();
|
||||||
|
MediaItem mediaItem =
|
||||||
|
new MediaItem.Builder()
|
||||||
|
.setTag(tag)
|
||||||
|
.setSourceUri(URI_MEDIA)
|
||||||
|
.setSubtitles(
|
||||||
|
Collections.singletonList(
|
||||||
|
new MediaItem.Subtitle(Uri.parse(URI_TEXT), MimeTypes.APPLICATION_TTML, "en")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem);
|
||||||
|
|
||||||
|
assertThat(mediaSource.getTag()).isEqualTo(tag);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSupportedTypes_coreModule_onlyOther() {
|
public void getSupportedTypes_coreModule_onlyOther() {
|
||||||
int[] supportedTypes =
|
int[] supportedTypes =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user