Skip to content

Commit 1461fb6

Browse files
authored
chore: support preferred languages on HLS redundant stream. (#14)
1 parent 5b1351a commit 1461fb6

File tree

4 files changed

+75
-14
lines changed

4 files changed

+75
-14
lines changed

demos/main/src/main/assets/media.exolist.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,13 @@
228228
"name": "WWE live, wwe",
229229
"uri": "https://dummy.imggaming.com/video?id=111449&live=true&dash=&realm=dce.wwe&usr=&pwd="
230230
},
231+
{
232+
"name": "WWE vod, wwe",
233+
"uri": "https://dummy.imggaming.com/video?id=530182&live=&dash=&realm=dce.wwe&usr=&pwd=",
234+
"subtitle_uri": "https://dve-subtitles.imggaming.com/530182/741299/vtt/subtitle-en-US-199647-1697490152197.vtt",
235+
"subtitle_mime_type": "text/vtt",
236+
"subtitle_language": "en"
237+
},
231238
{
232239
"name": "450830 DRM, adjara",
233240
"uri": "https://dummy.imggaming.com/video?id=450830&live=&dash=true&realm=dce.adjara&usr=&pwd="

demos/main/src/main/java/androidx/media3/demo/main/SampleChooserActivity.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,11 @@ public boolean onChildClick(
280280
List<MediaItem> mediaItems = playlistHolder.mediaItems;
281281
if (result != null && result.localConfiguration != null) {
282282
Log.i(TAG, "fetch video from backend - " + originUri.getQuery() + " >> " + result.localConfiguration.uri);
283+
if (playlistHolder.mediaItems.get(0).localConfiguration.subtitleConfigurations != null) {
284+
result = result.buildUpon()
285+
.setSubtitleConfigurations(playlistHolder.mediaItems.get(0).localConfiguration.subtitleConfigurations)
286+
.build();
287+
}
283288
mediaItems = Collections.singletonList(result);
284289
}
285290
IntentUtil.addToIntent(mediaItems, intent);

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/endeavor/TrackCollector.java

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
import androidx.media3.common.endeavor.WebUtil;
1212
import androidx.media3.common.util.Log;
1313
import androidx.media3.exoplayer.source.TrackGroupArray;
14+
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector;
1415
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
1516
import androidx.media3.exoplayer.trackselection.MappingTrackSelector;
1617
import androidx.media3.exoplayer.trackselection.TrackSelector;
18+
import com.google.common.collect.ImmutableList;
1719
import java.util.HashMap;
1820
import java.util.Iterator;
1921
import java.util.Map;
@@ -43,6 +45,7 @@ public TrackCollector(TrackSelector callback) {
4345
// May update status for the blacklistUntilTimes, videoTrackSelection, preferredAudioName and so on.
4446
public void onMappedTrackInfoChanged(
4547
MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
48+
DefaultTrackSelector.Parameters parameters,
4649
ExoTrackSelection.Definition[] overrideDefinitions) {
4750
this.noGroupConstraint = true;
4851
this.videoUseFixedSelection = false;
@@ -72,25 +75,22 @@ public void onMappedTrackInfoChanged(
7275
Format format = overrideDefinitions[i].group.getFormat(overrideDefinitions[i].tracks[0]);
7376
preferredAudioName = getFormatName(format);
7477
} else if (preferredAudioName == null) {
75-
preferredAudioName = "";
76-
for (int j = 0; j < trackGroups.length; j++) {
77-
TrackGroup track = trackGroups.get(j);
78-
for (int k = 0; k < track.length; k++) {
79-
Format format = track.getFormat(k);
80-
if ((format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0) {
81-
preferredAudioName = getFormatName(format);
82-
break;
83-
}
84-
}
78+
preferredAudioName = getParametersPreferred(trackGroups, parameters.preferredAudioLanguages);
79+
if (preferredAudioName == null) {
80+
preferredAudioName = getDefaultPreferred(trackGroups);
8581
}
8682
}
8783
} else if (C.TRACK_TYPE_TEXT == mappedTrackInfo.getRendererType(i)) {
8884
// Init the preferred text name.
8985
if (overrideDefinitions[i] != null) {
9086
Format format = overrideDefinitions[i].group.getFormat(overrideDefinitions[i].tracks[0]);
9187
preferredTextName = getFormatName(format);
92-
} else {
93-
preferredTextName = "";
88+
} else if (preferredTextName == null) {
89+
TrackGroupArray trackGroups = mappedTrackInfo.getTrackGroups(i);
90+
preferredTextName = getParametersPreferred(trackGroups, parameters.preferredTextLanguages);
91+
if (preferredTextName == null) {
92+
preferredTextName = "";
93+
}
9494
}
9595
}
9696
}
@@ -305,6 +305,55 @@ private TrackGroupArray getTrackGroups(int trackType) {
305305
return new TrackGroupArray();
306306
}
307307

308+
private String getParametersPreferred(
309+
TrackGroupArray trackGroups,
310+
ImmutableList<String> preferredLanguages) {
311+
if (preferredLanguages.size() == 0) {
312+
return null;
313+
}
314+
315+
int bestLanguageScore = 0;
316+
int bestLanguageIndex = Integer.MAX_VALUE;
317+
String preferredName = null;
318+
for (int i = 0; i < trackGroups.length; i++) {
319+
TrackGroup trackGroup = trackGroups.get(i);
320+
if (trackGroup.length == 0) {
321+
continue;
322+
}
323+
Format format = trackGroup.getFormat(0);
324+
for (int j = 0; j < preferredLanguages.size(); j++) {
325+
int score = DefaultTrackSelector.getFormatLanguageScore(
326+
format,
327+
preferredLanguages.get(j),
328+
/* allowUndeterminedFormatLanguage= */ false);
329+
if (score > 0) {
330+
if (j < bestLanguageIndex || (j == bestLanguageIndex && score > bestLanguageScore)) {
331+
bestLanguageIndex = j;
332+
bestLanguageScore = score;
333+
preferredName = getFormatName(format);
334+
}
335+
break;
336+
}
337+
}
338+
}
339+
return preferredName;
340+
}
341+
342+
private String getDefaultPreferred(TrackGroupArray trackGroups) {
343+
String preferredName = "";
344+
for (int i = 0; i < trackGroups.length; i++) {
345+
TrackGroup trackGroup = trackGroups.get(i);
346+
for (int j = 0; j < trackGroup.length; j++) {
347+
Format format = trackGroup.getFormat(j);
348+
if ((format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0) {
349+
preferredName = getFormatName(format);
350+
break;
351+
}
352+
}
353+
}
354+
return preferredName;
355+
}
356+
308357
private static int getMetadataEntrySize(Format format) {
309358
return (format == null || format.metadata == null ? 0 : format.metadata.length());
310359
}

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,7 +2388,7 @@ private void setParametersInternal(Parameters parameters) {
23882388
}
23892389
int rendererCount = mappedTrackInfo.getRendererCount();
23902390
// May update status of track collector for the preferredAudioName, blacklistUntilTimes and so on.
2391-
trackCollector.onMappedTrackInfoChanged(mappedTrackInfo, getOverrideDefinitions(mappedTrackInfo, parameters));
2391+
trackCollector.onMappedTrackInfoChanged(mappedTrackInfo, parameters, getOverrideDefinitions(mappedTrackInfo, parameters));
23922392
ExoTrackSelection.@NullableType Definition[] definitions =
23932393
selectAllTracks(
23942394
mappedTrackInfo,
@@ -3161,7 +3161,7 @@ protected static String normalizeUndeterminedLanguageToNull(@Nullable String lan
31613161
* 1 if the format language is undetermined and such a match is allowed, and a score of 0 if
31623162
* the languages don't match at all.
31633163
*/
3164-
protected static int getFormatLanguageScore(
3164+
public static int getFormatLanguageScore(
31653165
Format format, @Nullable String language, boolean allowUndeterminedFormatLanguage) {
31663166
if (!TextUtils.isEmpty(language) && language.equals(format.language)) {
31673167
// Full literal match of non-empty languages, including matches of an explicit "und" query.

0 commit comments

Comments
 (0)