DASH: Parse Role elements to select default audio/text tracks

Issue: #2058

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=144693705
This commit is contained in:
olly 2017-01-17 04:06:14 -08:00 committed by Oliver Woodman
parent 6e481178ea
commit 7f967f3057
6 changed files with 54 additions and 35 deletions

View File

@ -29,13 +29,13 @@ public class RepresentationTest extends TestCase {
String uri = "http://www.google.com";
SegmentBase base = new SingleSegmentBase(new RangedUri(null, 0, 1), 1, 0, 1, 1);
Format format = Format.createVideoContainerFormat("0", MimeTypes.APPLICATION_MP4, null,
MimeTypes.VIDEO_H264, 2500000, 1920, 1080, Format.NO_VALUE, null);
MimeTypes.VIDEO_H264, 2500000, 1920, 1080, Format.NO_VALUE, null, 0);
Representation representation = Representation.newInstance("test_stream_1", 3, format, uri,
base);
assertEquals("test_stream_1.0.3", representation.getCacheKey());
format = Format.createVideoContainerFormat("150", MimeTypes.APPLICATION_MP4, null,
MimeTypes.VIDEO_H264, 2500000, 1920, 1080, Format.NO_VALUE, null);
MimeTypes.VIDEO_H264, 2500000, 1920, 1080, Format.NO_VALUE, null, 0);
representation = Representation.newInstance("test_stream_1", Representation.REVISION_ID_DEFAULT,
format, uri, base);
assertEquals("test_stream_1.150.-1", representation.getCacheKey());

View File

@ -192,11 +192,11 @@ public final class Format implements Parcelable {
public static Format createVideoContainerFormat(String id, String containerMimeType,
String sampleMimeType, String codecs, int bitrate, int width, int height,
float frameRate, List<byte[]> initializationData) {
float frameRate, List<byte[]> initializationData, @C.SelectionFlags int selectionFlags) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, width,
height, frameRate, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, 0, null, NO_VALUE, OFFSET_SAMPLE_RELATIVE, initializationData, null,
null);
NO_VALUE, NO_VALUE, selectionFlags, null, NO_VALUE, OFFSET_SAMPLE_RELATIVE,
initializationData, null, null);
}
public static Format createVideoSampleFormat(String id, String sampleMimeType, String codecs,
@ -289,8 +289,8 @@ public final class Format implements Parcelable {
}
public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, @C.SelectionFlags int selectionFlags, String language,
int accessibilityChannel, DrmInitData drmInitData) {
int bitrate, @C.SelectionFlags int selectionFlags, String language, int accessibilityChannel,
DrmInitData drmInitData) {
return createTextSampleFormat(id, sampleMimeType, codecs, bitrate, selectionFlags, language,
accessibilityChannel, drmInitData, OFFSET_SAMPLE_RELATIVE);
}
@ -323,11 +323,13 @@ public final class Format implements Parcelable {
// Generic.
public static Format createContainerFormat(String id, String containerMimeType, String codecs,
String sampleMimeType, int bitrate) {
public static Format createContainerFormat(String id, String containerMimeType,
String sampleMimeType, String codecs, int bitrate, @C.SelectionFlags int selectionFlags,
String language) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, 0, null, NO_VALUE, OFFSET_SAMPLE_RELATIVE, null, null, null);
NO_VALUE, NO_VALUE, selectionFlags, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE, null, null,
null);
}
public static Format createSampleFormat(String id, String sampleMimeType,

View File

@ -243,6 +243,7 @@ public class DashManifestParser extends DefaultHandler
List<RepresentationInfo> representationInfos = new ArrayList<>();
List<InbandEventStream> adaptationSetInbandEventStreams = new ArrayList<>();
List<InbandEventStream> commonRepresentationInbandEventStreams = null;
@C.SelectionFlags int selectionFlags = 0;
boolean seenFirstBaseUrl = false;
do {
@ -260,10 +261,16 @@ public class DashManifestParser extends DefaultHandler
} else if (XmlPullParserUtil.isStartTag(xpp, "ContentComponent")) {
language = checkLanguageConsistency(language, xpp.getAttributeValue(null, "lang"));
contentType = checkContentTypeConsistency(contentType, parseContentType(xpp));
} else if (XmlPullParserUtil.isStartTag(xpp, "Role")) {
selectionFlags |= parseRole(xpp);
} else if (XmlPullParserUtil.isStartTag(xpp, "AudioChannelConfiguration")) {
audioChannels = parseAudioChannelConfiguration(xpp);
} else if (XmlPullParserUtil.isStartTag(xpp, "Accessibility")) {
accessibilityChannel = parseAccessibilityValue(xpp);
} else if (XmlPullParserUtil.isStartTag(xpp, "Representation")) {
RepresentationInfo representationInfo = parseRepresentation(xpp, baseUrl, mimeType, codecs,
width, height, frameRate, audioChannels, audioSamplingRate, language,
accessibilityChannel, segmentBase);
accessibilityChannel, selectionFlags, segmentBase);
contentType = checkContentTypeConsistency(contentType,
getContentType(representationInfo.format));
representationInfos.add(representationInfo);
@ -283,10 +290,6 @@ public class DashManifestParser extends DefaultHandler
}
}
}
} else if (XmlPullParserUtil.isStartTag(xpp, "AudioChannelConfiguration")) {
audioChannels = parseAudioChannelConfiguration(xpp);
} else if (XmlPullParserUtil.isStartTag(xpp, "Accessibility")) {
accessibilityChannel = parseAccessibilityValue(xpp);
} else if (XmlPullParserUtil.isStartTag(xpp, "SegmentBase")) {
segmentBase = parseSegmentBase(xpp, (SingleSegmentBase) segmentBase);
} else if (XmlPullParserUtil.isStartTag(xpp, "SegmentList")) {
@ -402,6 +405,24 @@ public class DashManifestParser extends DefaultHandler
return new InbandEventStream(schemeIdUri, value);
}
/**
* Parses a Role element.
*
* @param xpp The parser from which to read.
* @throws XmlPullParserException If an error occurs parsing the element.
* @throws IOException If an error occurs reading the element.
* @return {@link C.SelectionFlags} parsed from the element.
*/
protected int parseRole(XmlPullParser xpp) throws XmlPullParserException, IOException {
String schemeIdUri = parseString(xpp, "schemeIdUri", null);
String value = parseString(xpp, "value", null);
do {
xpp.next();
} while (!XmlPullParserUtil.isEndTag(xpp, "Role"));
return "urn:mpeg:dash:role:2011".equals(schemeIdUri) && "main".equals(value)
? C.SELECTION_FLAG_DEFAULT : 0;
}
/**
* Parses children of AdaptationSet elements not specifically parsed elsewhere.
*
@ -420,8 +441,8 @@ public class DashManifestParser extends DefaultHandler
String adaptationSetMimeType, String adaptationSetCodecs, int adaptationSetWidth,
int adaptationSetHeight, float adaptationSetFrameRate, int adaptationSetAudioChannels,
int adaptationSetAudioSamplingRate, String adaptationSetLanguage,
int adaptationSetAccessibilityChannel, SegmentBase segmentBase)
throws XmlPullParserException, IOException {
int adaptationSetAccessibilityChannel, @C.SelectionFlags int adaptationSetSelectionFlags,
SegmentBase segmentBase) throws XmlPullParserException, IOException {
String id = xpp.getAttributeValue(null, "id");
int bandwidth = parseInt(xpp, "bandwidth", Format.NO_VALUE);
@ -463,7 +484,7 @@ public class DashManifestParser extends DefaultHandler
Format format = buildFormat(id, mimeType, width, height, frameRate, audioChannels,
audioSamplingRate, bandwidth, adaptationSetLanguage, adaptationSetAccessibilityChannel,
codecs);
adaptationSetSelectionFlags, codecs);
segmentBase = segmentBase != null ? segmentBase : new SingleSegmentBase();
return new RepresentationInfo(format, baseUrl, segmentBase, drmSchemeDatas, inbandEventStreams);
@ -471,27 +492,23 @@ public class DashManifestParser extends DefaultHandler
protected Format buildFormat(String id, String containerMimeType, int width, int height,
float frameRate, int audioChannels, int audioSamplingRate, int bitrate, String language,
int accessiblityChannel, String codecs) {
int accessiblityChannel, @C.SelectionFlags int selectionFlags, String codecs) {
String sampleMimeType = getSampleMimeType(containerMimeType, codecs);
if (sampleMimeType != null) {
if (MimeTypes.isVideo(sampleMimeType)) {
return Format.createVideoContainerFormat(id, containerMimeType, sampleMimeType, codecs,
bitrate, width, height, frameRate, null);
bitrate, width, height, frameRate, null, selectionFlags);
} else if (MimeTypes.isAudio(sampleMimeType)) {
return Format.createAudioContainerFormat(id, containerMimeType, sampleMimeType, codecs,
bitrate, audioChannels, audioSamplingRate, null, 0, language);
} else if (mimeTypeIsRawText(sampleMimeType)) {
bitrate, audioChannels, audioSamplingRate, null, selectionFlags, language);
} else if (mimeTypeIsRawText(sampleMimeType)
|| MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
return Format.createTextContainerFormat(id, containerMimeType, sampleMimeType, codecs,
bitrate, 0, language, accessiblityChannel);
} else if (containerMimeType.equals(MimeTypes.APPLICATION_RAWCC)) {
return Format.createTextContainerFormat(id, containerMimeType, sampleMimeType, codecs,
bitrate, 0, language, accessiblityChannel);
} else {
return Format.createContainerFormat(id, containerMimeType, codecs, sampleMimeType, bitrate);
bitrate, selectionFlags, language, accessiblityChannel);
}
} else {
return Format.createContainerFormat(id, containerMimeType, codecs, sampleMimeType, bitrate);
}
return Format.createContainerFormat(id, containerMimeType, sampleMimeType, codecs, bitrate,
selectionFlags, language);
}
protected Representation buildRepresentation(RepresentationInfo representationInfo,

View File

@ -40,7 +40,7 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
public static HlsUrl createMediaPlaylistHlsUrl(String baseUri) {
Format format = Format.createContainerFormat("0", MimeTypes.APPLICATION_M3U8, null, null,
Format.NO_VALUE);
Format.NO_VALUE, 0, null);
return new HlsUrl(null, baseUri, format, null, null, null);
}

View File

@ -240,7 +240,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
line = iterator.next();
String name = Integer.toString(variants.size());
Format format = Format.createVideoContainerFormat(name, MimeTypes.APPLICATION_M3U8, null,
codecs, bitrate, width, height, Format.NO_VALUE, null);
codecs, bitrate, width, height, Format.NO_VALUE, null, 0);
variants.add(new HlsMasterPlaylist.HlsUrl(name, line, format, null, null, null));
}
}

View File

@ -625,7 +625,7 @@ public class SsManifestParser implements ParsingLoadable.Parser<SsManifest> {
List<byte[]> codecSpecificData = buildCodecSpecificData(
parser.getAttributeValue(null, KEY_CODEC_PRIVATE_DATA));
format = Format.createVideoContainerFormat(id, MimeTypes.VIDEO_MP4, sampleMimeType, null,
bitrate, width, height, Format.NO_VALUE, codecSpecificData);
bitrate, width, height, Format.NO_VALUE, codecSpecificData, 0);
} else if (type == C.TRACK_TYPE_AUDIO) {
sampleMimeType = sampleMimeType == null ? MimeTypes.AUDIO_AAC : sampleMimeType;
int channels = parseRequiredInt(parser, KEY_CHANNELS);
@ -644,8 +644,8 @@ public class SsManifestParser implements ParsingLoadable.Parser<SsManifest> {
format = Format.createTextContainerFormat(id, MimeTypes.APPLICATION_MP4, sampleMimeType,
null, bitrate, 0, language);
} else {
format = Format.createContainerFormat(id, MimeTypes.APPLICATION_MP4, null, sampleMimeType,
bitrate);
format = Format.createContainerFormat(id, MimeTypes.APPLICATION_MP4, sampleMimeType, null,
bitrate, 0, null);
}
}