Add HlsMetadataEntries to HlsMasterPlaylist's variants and renditions

PiperOrigin-RevId: 243304549
This commit is contained in:
aquilescanta 2019-04-12 19:49:19 +01:00 committed by Oliver Woodman
parent b2c29da6b3
commit 97acc681d1
2 changed files with 59 additions and 27 deletions

View file

@ -120,6 +120,11 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
/* subtitleGroupId= */ null, /* subtitleGroupId= */ null,
/* captionGroupId= */ null); /* captionGroupId= */ null);
} }
/** Returns a copy of this instance with the given {@link Format}. */
public Variant copyWithFormat(Format format) {
return new Variant(url, format, videoGroupId, audioGroupId, subtitleGroupId, captionGroupId);
}
} }
/** A rendition (i.e. an #EXT-X-MEDIA tag) in a master playlist. */ /** A rendition (i.e. an #EXT-X-MEDIA tag) in a master playlist. */

View file

@ -25,11 +25,15 @@ import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
import com.google.android.exoplayer2.extractor.mp4.PsshAtomUtil; import com.google.android.exoplayer2.extractor.mp4.PsshAtomUtil;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.source.UnrecognizedInputFormatException; import com.google.android.exoplayer2.source.UnrecognizedInputFormatException;
import com.google.android.exoplayer2.source.hls.HlsTrackMetadataEntry;
import com.google.android.exoplayer2.source.hls.HlsTrackMetadataEntry.VariantInfo;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Rendition; import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Rendition;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Variant; import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Variant;
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment; import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment;
import com.google.android.exoplayer2.upstream.ParsingLoadable; import com.google.android.exoplayer2.upstream.ParsingLoadable;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.UriUtil; import com.google.android.exoplayer2.util.UriUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
@ -252,10 +256,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, String baseUri) private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, String baseUri)
throws IOException { throws IOException {
HashSet<String> variantUrls = new HashSet<>(); HashMap<Uri, ArrayList<VariantInfo>> urlToVariantInfos = new HashMap<>();
HashMap<String, String> variableDefinitions = new HashMap<>(); HashMap<String, String> variableDefinitions = new HashMap<>();
ArrayList<Variant> variants = new ArrayList<>(); ArrayList<Variant> variants = new ArrayList<>();
ArrayList<Variant> deduplicatedVariants = new ArrayList<>();
ArrayList<Rendition> videos = new ArrayList<>(); ArrayList<Rendition> videos = new ArrayList<>();
ArrayList<Rendition> audios = new ArrayList<>(); ArrayList<Rendition> audios = new ArrayList<>();
ArrayList<Rendition> subtitles = new ArrayList<>(); ArrayList<Rendition> subtitles = new ArrayList<>();
@ -357,10 +360,30 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
new Variant( new Variant(
uri, format, videoGroupId, audioGroupId, subtitlesGroupId, closedCaptionsGroupId); uri, format, videoGroupId, audioGroupId, subtitlesGroupId, closedCaptionsGroupId);
variants.add(variant); variants.add(variant);
// TODO: Don't deduplicate variants by URL. ArrayList<VariantInfo> variantInfosForUrl = urlToVariantInfos.get(uri);
if (variantUrls.add(line)) { if (variantInfosForUrl == null) {
deduplicatedVariants.add(variant); variantInfosForUrl = new ArrayList<>();
urlToVariantInfos.put(uri, variantInfosForUrl);
} }
variantInfosForUrl.add(
new VariantInfo(
bitrate, videoGroupId, audioGroupId, subtitlesGroupId, closedCaptionsGroupId));
}
}
// TODO: Don't deduplicate variants by URL.
ArrayList<Variant> deduplicatedVariants = new ArrayList<>();
HashSet<Uri> urlsInDeduplicatedVariants = new HashSet<>();
for (int i = 0; i < variants.size(); i++) {
Variant variant = variants.get(i);
if (urlsInDeduplicatedVariants.add(variant.url)) {
Assertions.checkState(variant.format.metadata == null);
HlsTrackMetadataEntry hlsMetadataEntry =
new HlsTrackMetadataEntry(
/* groupId= */ null, /* name= */ null, urlToVariantInfos.get(variant.url));
deduplicatedVariants.add(
variant.copyWithFormat(
variant.format.copyWithMetadata(new Metadata(hlsMetadataEntry))));
} }
} }
@ -375,6 +398,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
@C.RoleFlags int roleFlags = parseRoleFlags(line, variableDefinitions); @C.RoleFlags int roleFlags = parseRoleFlags(line, variableDefinitions);
String formatId = groupId + ":" + name; String formatId = groupId + ":" + name;
Format format; Format format;
Metadata metadata =
new Metadata(new HlsTrackMetadataEntry(groupId, name, Collections.emptyList()));
switch (parseStringAttr(line, REGEX_TYPE, variableDefinitions)) { switch (parseStringAttr(line, REGEX_TYPE, variableDefinitions)) {
case TYPE_VIDEO: case TYPE_VIDEO:
Variant variant = getVariantWithVideoGroup(variants, groupId); Variant variant = getVariantWithVideoGroup(variants, groupId);
@ -392,18 +417,19 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
String sampleMimeType = codecs != null ? MimeTypes.getMediaMimeType(codecs) : null; String sampleMimeType = codecs != null ? MimeTypes.getMediaMimeType(codecs) : null;
format = format =
Format.createVideoContainerFormat( Format.createVideoContainerFormat(
/* id= */ formatId, /* id= */ formatId,
/* label= */ name, /* label= */ name,
/* containerMimeType= */ MimeTypes.APPLICATION_M3U8, /* containerMimeType= */ MimeTypes.APPLICATION_M3U8,
sampleMimeType, sampleMimeType,
codecs, codecs,
/* bitrate= */ Format.NO_VALUE, /* bitrate= */ Format.NO_VALUE,
width, width,
height, height,
frameRate, frameRate,
/* initializationData= */ null, /* initializationData= */ null,
selectionFlags, selectionFlags,
roleFlags); roleFlags)
.copyWithMetadata(metadata);
if (uri == null) { if (uri == null) {
// TODO: Remove this case and add a Rendition with a null uri to videos. // TODO: Remove this case and add a Rendition with a null uri to videos.
} else { } else {
@ -436,21 +462,22 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
// TODO: Remove muxedAudioFormat and add a Rendition with a null uri to audios. // TODO: Remove muxedAudioFormat and add a Rendition with a null uri to audios.
muxedAudioFormat = format; muxedAudioFormat = format;
} else { } else {
audios.add(new Rendition(uri, format, groupId, name)); audios.add(new Rendition(uri, format.copyWithMetadata(metadata), groupId, name));
} }
break; break;
case TYPE_SUBTITLES: case TYPE_SUBTITLES:
format = format =
Format.createTextContainerFormat( Format.createTextContainerFormat(
/* id= */ formatId, /* id= */ formatId,
/* label= */ name, /* label= */ name,
/* containerMimeType= */ MimeTypes.APPLICATION_M3U8, /* containerMimeType= */ MimeTypes.APPLICATION_M3U8,
/* sampleMimeType= */ MimeTypes.TEXT_VTT, /* sampleMimeType= */ MimeTypes.TEXT_VTT,
/* codecs= */ null, /* codecs= */ null,
/* bitrate= */ Format.NO_VALUE, /* bitrate= */ Format.NO_VALUE,
selectionFlags, selectionFlags,
roleFlags, roleFlags,
language); language)
.copyWithMetadata(metadata);
subtitles.add(new Rendition(uri, format, groupId, name)); subtitles.add(new Rendition(uri, format, groupId, name));
break; break;
case TYPE_CLOSED_CAPTIONS: case TYPE_CLOSED_CAPTIONS: