Skip to content

Commit

Permalink
Add support for subtitle files in the demo app
Browse files Browse the repository at this point in the history
issue:#5523
PiperOrigin-RevId: 277927555
  • Loading branch information
icbaker authored and ojw28 committed Nov 5, 2019
1 parent c5c5007 commit 07e93c1
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 7 deletions.
2 changes: 2 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@
* Update the ffmpeg extension to release 4.2. It is necessary to rebuild the
native part of the extension after this change, following the instructions in
the extension's readme.
* Add support for subtitle files to the demo app
([#5523](https://github.com/google/ExoPlayer/issues/5523)).

### 2.10.6 (2019-10-17) ###

Expand Down
12 changes: 12 additions & 0 deletions demos/main/src/main/assets/media.exolist.json
Original file line number Diff line number Diff line change
Expand Up @@ -582,5 +582,17 @@
"spherical_stereo_mode": "top_bottom"
}
]
},
{
"name": "Subtitles",
"samples": [
{
"name": "TTML",
"uri": "https://html5demos.com/assets/dizzy.mp4",
"subtitle_uri": "https://storage.googleapis.com/exoplayer-test-media-1/ttml/netflix_ttml_sample.xml",
"subtitle_mime_type": "application/ttml+xml",
"subtitle_language": "en"
}
]
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.C.ContentType;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackPreparer;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.RenderersFactory;
Expand All @@ -53,7 +54,9 @@
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.source.MergingMediaSource;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.SingleSampleMediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
Expand Down Expand Up @@ -114,8 +117,11 @@ public class PlayerActivity extends AppCompatActivity
public static final String DRM_KEY_REQUEST_PROPERTIES_EXTRA = "drm_key_request_properties";
public static final String DRM_MULTI_SESSION_EXTRA = "drm_multi_session";
public static final String PREFER_EXTENSION_DECODERS_EXTRA = "prefer_extension_decoders";
public static final String TUNNELING = "tunneling";
public static final String TUNNELING_EXTRA = "tunneling";
public static final String AD_TAG_URI_EXTRA = "ad_tag_uri";
public static final String SUBTITLE_URI_EXTRA = "subtitle_uri";
public static final String SUBTITLE_MIME_TYPE_EXTRA = "subtitle_mime_type";
public static final String SUBTITLE_LANGUAGE_EXTRA = "subtitle_language";
// For backwards compatibility only.
public static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid";

Expand Down Expand Up @@ -204,7 +210,7 @@ public void onCreate(Bundle savedInstanceState) {
} else {
DefaultTrackSelector.ParametersBuilder builder =
new DefaultTrackSelector.ParametersBuilder(/* context= */ this);
boolean tunneling = intent.getBooleanExtra(TUNNELING, false);
boolean tunneling = intent.getBooleanExtra(TUNNELING_EXTRA, false);
if (Util.SDK_INT >= 21 && tunneling) {
builder.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(/* context= */ this));
}
Expand Down Expand Up @@ -424,6 +430,19 @@ private MediaSource createTopLevelMediaSource(Intent intent) {
MediaSource[] mediaSources = new MediaSource[samples.length];
for (int i = 0; i < samples.length; i++) {
mediaSources[i] = createLeafMediaSource(samples[i]);
Sample.SubtitleInfo subtitleInfo = samples[i].subtitleInfo;
if (subtitleInfo != null) {
Format subtitleFormat =
Format.createTextSampleFormat(
/* id= */ null,
subtitleInfo.mimeType,
/* selectionFlags= */ 0,
subtitleInfo.language);
MediaSource subtitleMediaSource =
new SingleSampleMediaSource.Factory(dataSourceFactory)
.createMediaSource(subtitleInfo.uri, subtitleFormat, C.TIME_UNSET);
mediaSources[i] = new MergingMediaSource(mediaSources[i], subtitleMediaSource);
}
}
MediaSource mediaSource =
mediaSources.length == 1 ? mediaSources[0] : new ConcatenatingMediaSource(mediaSources);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
import static com.google.android.exoplayer2.demo.PlayerActivity.DRM_SCHEME_UUID_EXTRA;
import static com.google.android.exoplayer2.demo.PlayerActivity.EXTENSION_EXTRA;
import static com.google.android.exoplayer2.demo.PlayerActivity.IS_LIVE_EXTRA;
import static com.google.android.exoplayer2.demo.PlayerActivity.SUBTITLE_LANGUAGE_EXTRA;
import static com.google.android.exoplayer2.demo.PlayerActivity.SUBTITLE_MIME_TYPE_EXTRA;
import static com.google.android.exoplayer2.demo.PlayerActivity.SUBTITLE_URI_EXTRA;
import static com.google.android.exoplayer2.demo.PlayerActivity.URI_EXTRA;

import android.content.Intent;
Expand Down Expand Up @@ -51,7 +54,8 @@ public static UriSample createFromIntent(Uri uri, Intent intent, String extrasKe
isLive,
DrmInfo.createFromIntent(intent, extrasKeySuffix),
adTagUri,
/* sphericalStereoMode= */ null);
/* sphericalStereoMode= */ null,
SubtitleInfo.createFromIntent(intent, extrasKeySuffix));
}

public final Uri uri;
Expand All @@ -60,6 +64,7 @@ public static UriSample createFromIntent(Uri uri, Intent intent, String extrasKe
public final DrmInfo drmInfo;
public final Uri adTagUri;
@Nullable public final String sphericalStereoMode;
@Nullable SubtitleInfo subtitleInfo;

public UriSample(
String name,
Expand All @@ -68,14 +73,16 @@ public UriSample(
boolean isLive,
DrmInfo drmInfo,
Uri adTagUri,
@Nullable String sphericalStereoMode) {
@Nullable String sphericalStereoMode,
@Nullable SubtitleInfo subtitleInfo) {
super(name);
this.uri = uri;
this.extension = extension;
this.isLive = isLive;
this.drmInfo = drmInfo;
this.adTagUri = adTagUri;
this.sphericalStereoMode = sphericalStereoMode;
this.subtitleInfo = subtitleInfo;
}

@Override
Expand All @@ -100,6 +107,9 @@ private void addPlayerConfigToIntent(Intent intent, String extrasKeySuffix) {
if (drmInfo != null) {
drmInfo.addToIntent(intent, extrasKeySuffix);
}
if (subtitleInfo != null) {
subtitleInfo.addToIntent(intent, extrasKeySuffix);
}
}
}

Expand Down Expand Up @@ -167,6 +177,36 @@ public void addToIntent(Intent intent, String extrasKeySuffix) {
}
}

public static final class SubtitleInfo {

@Nullable
public static SubtitleInfo createFromIntent(Intent intent, String extrasKeySuffix) {
if (!intent.hasExtra(SUBTITLE_URI_EXTRA + extrasKeySuffix)) {
return null;
}
return new SubtitleInfo(
Uri.parse(intent.getStringExtra(SUBTITLE_URI_EXTRA + extrasKeySuffix)),
intent.getStringExtra(SUBTITLE_MIME_TYPE_EXTRA + extrasKeySuffix),
intent.getStringExtra(SUBTITLE_LANGUAGE_EXTRA + extrasKeySuffix));
}

public final Uri uri;
public final String mimeType;
@Nullable public final String language;

public SubtitleInfo(Uri uri, String mimeType, @Nullable String language) {
this.uri = Assertions.checkNotNull(uri);
this.mimeType = Assertions.checkNotNull(mimeType);
this.language = language;
}

public void addToIntent(Intent intent, String extrasKeySuffix) {
intent.putExtra(SUBTITLE_URI_EXTRA + extrasKeySuffix, uri.toString());
intent.putExtra(SUBTITLE_MIME_TYPE_EXTRA + extrasKeySuffix, mimeType);
intent.putExtra(SUBTITLE_LANGUAGE_EXTRA + extrasKeySuffix, language);
}
}

public static Sample createFromIntent(Intent intent) {
if (ACTION_VIEW_LIST.equals(intent.getAction())) {
ArrayList<String> intentUris = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public boolean onChildClick(
? PlayerActivity.ABR_ALGORITHM_RANDOM
: PlayerActivity.ABR_ALGORITHM_DEFAULT;
intent.putExtra(PlayerActivity.ABR_ALGORITHM_EXTRA, abrAlgorithm);
intent.putExtra(PlayerActivity.TUNNELING, isNonNullAndChecked(tunnelingMenuItem));
intent.putExtra(PlayerActivity.TUNNELING_EXTRA, isNonNullAndChecked(tunnelingMenuItem));
sample.addToIntent(intent);
startActivity(intent);
return true;
Expand Down Expand Up @@ -311,6 +311,10 @@ private Sample readEntry(JsonReader reader, boolean insidePlaylist) throws IOExc
ArrayList<UriSample> playlistSamples = null;
String adTagUri = null;
String sphericalStereoMode = null;
List<Sample.SubtitleInfo> subtitleInfos = new ArrayList<>();
Uri subtitleUri = null;
String subtitleMimeType = null;
String subtitleLanguage = null;

reader.beginObject();
while (reader.hasNext()) {
Expand Down Expand Up @@ -352,7 +356,7 @@ private Sample readEntry(JsonReader reader, boolean insidePlaylist) throws IOExc
playlistSamples = new ArrayList<>();
reader.beginArray();
while (reader.hasNext()) {
playlistSamples.add((UriSample) readEntry(reader, true));
playlistSamples.add((UriSample) readEntry(reader, /* insidePlaylist= */ true));
}
reader.endArray();
break;
Expand All @@ -364,6 +368,15 @@ private Sample readEntry(JsonReader reader, boolean insidePlaylist) throws IOExc
!insidePlaylist, "Invalid attribute on nested item: spherical_stereo_mode");
sphericalStereoMode = reader.nextString();
break;
case "subtitle_uri":
subtitleUri = Uri.parse(reader.nextString());
break;
case "subtitle_mime_type":
subtitleMimeType = reader.nextString();
break;
case "subtitle_language":
subtitleLanguage = reader.nextString();
break;
default:
throw new ParserException("Unsupported attribute name: " + name);
}
Expand All @@ -377,6 +390,14 @@ private Sample readEntry(JsonReader reader, boolean insidePlaylist) throws IOExc
drmLicenseUrl,
drmKeyRequestProperties,
drmMultiSession);
Sample.SubtitleInfo subtitleInfo =
subtitleUri == null
? null
: new Sample.SubtitleInfo(
subtitleUri,
Assertions.checkNotNull(
subtitleMimeType, "subtitle_mime_type is required if subtitle_uri is set."),
subtitleLanguage);
if (playlistSamples != null) {
UriSample[] playlistSamplesArray = playlistSamples.toArray(new UriSample[0]);
return new PlaylistSample(sampleName, playlistSamplesArray);
Expand All @@ -388,7 +409,8 @@ private Sample readEntry(JsonReader reader, boolean insidePlaylist) throws IOExc
isLive,
drmInfo,
adTagUri != null ? Uri.parse(adTagUri) : null,
sphericalStereoMode);
sphericalStereoMode,
subtitleInfo);
}
}

Expand Down

0 comments on commit 07e93c1

Please sign in to comment.