use of com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist in project ExoPlayer by google.
the class HlsMasterPlaylistParserTest method testPlaylistWithClosedCaption.
public void testPlaylistWithClosedCaption() throws IOException {
HlsMasterPlaylist playlist = parseMasterPlaylist(PLAYLIST_URI, MASTER_PLAYLIST_WITH_CC);
assertEquals(1, playlist.muxedCaptionFormats.size());
Format closedCaptionFormat = playlist.muxedCaptionFormats.get(0);
assertEquals(MimeTypes.APPLICATION_CEA708, closedCaptionFormat.sampleMimeType);
assertEquals(4, closedCaptionFormat.accessibilityChannel);
assertEquals("es", closedCaptionFormat.language);
}
use of com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist in project ExoPlayer by google.
the class HlsPlaylistParser method parseMasterPlaylist.
private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, String baseUri) throws IOException {
ArrayList<HlsMasterPlaylist.HlsUrl> variants = new ArrayList<>();
ArrayList<HlsMasterPlaylist.HlsUrl> audios = new ArrayList<>();
ArrayList<HlsMasterPlaylist.HlsUrl> subtitles = new ArrayList<>();
Format muxedAudioFormat = null;
ArrayList<Format> muxedCaptionFormats = new ArrayList<>();
String line;
while (iterator.hasNext()) {
line = iterator.next();
if (line.startsWith(TAG_MEDIA)) {
@C.SelectionFlags int selectionFlags = parseSelectionFlags(line);
String uri = parseOptionalStringAttr(line, REGEX_URI);
String id = parseStringAttr(line, REGEX_NAME);
String language = parseOptionalStringAttr(line, REGEX_LANGUAGE);
Format format;
switch(parseStringAttr(line, REGEX_TYPE)) {
case TYPE_AUDIO:
format = Format.createAudioContainerFormat(id, MimeTypes.APPLICATION_M3U8, null, null, Format.NO_VALUE, Format.NO_VALUE, Format.NO_VALUE, null, selectionFlags, language);
if (uri == null) {
muxedAudioFormat = format;
} else {
audios.add(new HlsMasterPlaylist.HlsUrl(uri, format));
}
break;
case TYPE_SUBTITLES:
format = Format.createTextContainerFormat(id, MimeTypes.APPLICATION_M3U8, MimeTypes.TEXT_VTT, null, Format.NO_VALUE, selectionFlags, language);
subtitles.add(new HlsMasterPlaylist.HlsUrl(uri, format));
break;
case TYPE_CLOSED_CAPTIONS:
String instreamId = parseStringAttr(line, REGEX_INSTREAM_ID);
String mimeType;
int accessibilityChannel;
if (instreamId.startsWith("CC")) {
mimeType = MimeTypes.APPLICATION_CEA608;
accessibilityChannel = Integer.parseInt(instreamId.substring(2));
} else /* starts with SERVICE */
{
mimeType = MimeTypes.APPLICATION_CEA708;
accessibilityChannel = Integer.parseInt(instreamId.substring(7));
}
muxedCaptionFormats.add(Format.createTextContainerFormat(id, null, mimeType, null, Format.NO_VALUE, selectionFlags, language, accessibilityChannel));
break;
default:
// Do nothing.
break;
}
} else if (line.startsWith(TAG_STREAM_INF)) {
int bitrate = parseIntAttr(line, REGEX_BANDWIDTH);
String codecs = parseOptionalStringAttr(line, REGEX_CODECS);
String resolutionString = parseOptionalStringAttr(line, REGEX_RESOLUTION);
int width;
int height;
if (resolutionString != null) {
String[] widthAndHeight = resolutionString.split("x");
width = Integer.parseInt(widthAndHeight[0]);
height = Integer.parseInt(widthAndHeight[1]);
if (width <= 0 || height <= 0) {
// Resolution string is invalid.
width = Format.NO_VALUE;
height = Format.NO_VALUE;
}
} else {
width = Format.NO_VALUE;
height = Format.NO_VALUE;
}
line = iterator.next();
Format format = Format.createVideoContainerFormat(Integer.toString(variants.size()), MimeTypes.APPLICATION_M3U8, null, codecs, bitrate, width, height, Format.NO_VALUE, null, 0);
variants.add(new HlsMasterPlaylist.HlsUrl(line, format));
}
}
return new HlsMasterPlaylist(baseUri, variants, audios, subtitles, muxedAudioFormat, muxedCaptionFormats);
}
use of com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist in project ExoPlayer by google.
the class HlsMediaPeriod method buildAndPrepareSampleStreamWrappers.
// Internal methods.
private void buildAndPrepareSampleStreamWrappers() {
HlsMasterPlaylist masterPlaylist = playlistTracker.getMasterPlaylist();
// Build the default stream wrapper.
List<HlsUrl> selectedVariants = new ArrayList<>(masterPlaylist.variants);
ArrayList<HlsUrl> definiteVideoVariants = new ArrayList<>();
ArrayList<HlsUrl> definiteAudioOnlyVariants = new ArrayList<>();
for (int i = 0; i < selectedVariants.size(); i++) {
HlsUrl variant = selectedVariants.get(i);
if (variant.format.height > 0 || variantHasExplicitCodecWithPrefix(variant, "avc")) {
definiteVideoVariants.add(variant);
} else if (variantHasExplicitCodecWithPrefix(variant, "mp4a")) {
definiteAudioOnlyVariants.add(variant);
}
}
if (!definiteVideoVariants.isEmpty()) {
// We've identified some variants as definitely containing video. Assume variants within the
// master playlist are marked consistently, and hence that we have the full set. Filter out
// any other variants, which are likely to be audio only.
selectedVariants = definiteVideoVariants;
} else if (definiteAudioOnlyVariants.size() < selectedVariants.size()) {
// We've identified some variants, but not all, as being audio only. Filter them out to leave
// the remaining variants, which are likely to contain video.
selectedVariants.removeAll(definiteAudioOnlyVariants);
} else {
// Leave the enabled variants unchanged. They're likely either all video or all audio.
}
List<HlsUrl> audioRenditions = masterPlaylist.audios;
List<HlsUrl> subtitleRenditions = masterPlaylist.subtitles;
sampleStreamWrappers = new HlsSampleStreamWrapper[1 + /* variants */
audioRenditions.size() + subtitleRenditions.size()];
int currentWrapperIndex = 0;
pendingPrepareCount = sampleStreamWrappers.length;
Assertions.checkArgument(!selectedVariants.isEmpty());
HlsUrl[] variants = new HlsMasterPlaylist.HlsUrl[selectedVariants.size()];
selectedVariants.toArray(variants);
HlsSampleStreamWrapper sampleStreamWrapper = buildSampleStreamWrapper(C.TRACK_TYPE_DEFAULT, variants, masterPlaylist.muxedAudioFormat, masterPlaylist.muxedCaptionFormats);
sampleStreamWrappers[currentWrapperIndex++] = sampleStreamWrapper;
sampleStreamWrapper.setIsTimestampMaster(true);
sampleStreamWrapper.continuePreparing();
// Build audio stream wrappers.
for (int i = 0; i < audioRenditions.size(); i++) {
sampleStreamWrapper = buildSampleStreamWrapper(C.TRACK_TYPE_AUDIO, new HlsUrl[] { audioRenditions.get(i) }, null, Collections.<Format>emptyList());
sampleStreamWrappers[currentWrapperIndex++] = sampleStreamWrapper;
sampleStreamWrapper.continuePreparing();
}
// Build subtitle stream wrappers.
for (int i = 0; i < subtitleRenditions.size(); i++) {
HlsUrl url = subtitleRenditions.get(i);
sampleStreamWrapper = buildSampleStreamWrapper(C.TRACK_TYPE_TEXT, new HlsUrl[] { url }, null, Collections.<Format>emptyList());
sampleStreamWrapper.prepareSingleTrack(url.format);
sampleStreamWrappers[currentWrapperIndex++] = sampleStreamWrapper;
}
}
Aggregations