Add some initial plumbing for DASH EMSG support

Issue: #2176

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=143554094
This commit is contained in:
olly 2017-01-04 07:57:13 -08:00 committed by Oliver Woodman
parent 21762622ac
commit 44d6b1a271
3 changed files with 141 additions and 8 deletions

View File

@ -23,18 +23,48 @@ import java.util.List;
*/
public class AdaptationSet {
public static final int UNSET_ID = -1;
/**
* Value of {@link #id} indicating no value is set.=
*/
public static final int ID_UNSET = -1;
/**
* A non-negative identifier for the adaptation set that's unique in the scope of its containing
* period, or {@link #ID_UNSET} if not specified.
*/
public final int id;
/**
* The type of the adaptation set. One of the {@link com.google.android.exoplayer2.C}
* {@code TRACK_TYPE_*} constants.
*/
public final int type;
/**
* The {@link Representation}s in the adaptation set.
*/
public final List<Representation> representations;
public AdaptationSet(int id, int type, List<Representation> representations) {
/**
* The {@link InbandEventStream}s contained by all {@link Representation}s in the adaptation set.
*/
public final List<InbandEventStream> inbandEventStreams;
/**
* @param id A non-negative identifier for the adaptation set that's unique in the scope of its
* containing period, or {@link #ID_UNSET} if not specified.
* @param type The type of the adaptation set. One of the {@link com.google.android.exoplayer2.C}
* {@code TRACK_TYPE_*} constants.
* @param representations The {@link Representation}s in the adaptation set.
* @param inbandEventStreams The {@link InbandEventStream}s contained by all
* {@link Representation}s in the adaptation set.
*/
public AdaptationSet(int id, int type, List<Representation> representations,
List<InbandEventStream> inbandEventStreams) {
this.id = id;
this.type = type;
this.representations = Collections.unmodifiableList(representations);
this.inbandEventStreams = Collections.unmodifiableList(inbandEventStreams);
}
}

View File

@ -227,7 +227,7 @@ public class DashManifestParser extends DefaultHandler
protected AdaptationSet parseAdaptationSet(XmlPullParser xpp, String baseUrl,
SegmentBase segmentBase) throws XmlPullParserException, IOException {
int id = parseInt(xpp, "id", AdaptationSet.UNSET_ID);
int id = parseInt(xpp, "id", AdaptationSet.ID_UNSET);
int contentType = parseContentType(xpp);
String mimeType = xpp.getAttributeValue(null, "mimeType");
@ -241,6 +241,8 @@ public class DashManifestParser extends DefaultHandler
int accessibilityChannel = Format.NO_VALUE;
ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>();
List<RepresentationInfo> representationInfos = new ArrayList<>();
List<InbandEventStream> adaptationSetInbandEventStreams = new ArrayList<>();
List<InbandEventStream> commonRepresentationInbandEventStreams = null;
boolean seenFirstBaseUrl = false;
do {
@ -265,6 +267,22 @@ public class DashManifestParser extends DefaultHandler
contentType = checkContentTypeConsistency(contentType,
getContentType(representationInfo.format));
representationInfos.add(representationInfo);
// Initialize or update InbandEventStream elements defined in all child Representations.
List<InbandEventStream> inbandEventStreams = representationInfo.inbandEventStreams;
if (commonRepresentationInbandEventStreams == null) {
// Initialize with the elements defined in this representation.
commonRepresentationInbandEventStreams = new ArrayList<>(inbandEventStreams);
} else {
// Remove elements that are not also defined in this representation.
for (int i = commonRepresentationInbandEventStreams.size() - 1; i >= 0; i--) {
InbandEventStream inbandEventStream = commonRepresentationInbandEventStreams.get(i);
if (!inbandEventStreams.contains(inbandEventStream)) {
Log.w(TAG, "Ignoring InbandEventStream element not defined on all Representations: "
+ inbandEventStream);
commonRepresentationInbandEventStreams.remove(i);
}
}
}
} else if (XmlPullParserUtil.isStartTag(xpp, "AudioChannelConfiguration")) {
audioChannels = parseAudioChannelConfiguration(xpp);
} else if (XmlPullParserUtil.isStartTag(xpp, "Accessibility")) {
@ -275,23 +293,34 @@ public class DashManifestParser extends DefaultHandler
segmentBase = parseSegmentList(xpp, (SegmentList) segmentBase);
} else if (XmlPullParserUtil.isStartTag(xpp, "SegmentTemplate")) {
segmentBase = parseSegmentTemplate(xpp, (SegmentTemplate) segmentBase);
} else if (XmlPullParserUtil.isStartTag(xpp, "InbandEventStream")) {
adaptationSetInbandEventStreams.add(parseInbandEventStream(xpp));
} else if (XmlPullParserUtil.isStartTag(xpp)) {
parseAdaptationSetChild(xpp);
}
} while (!XmlPullParserUtil.isEndTag(xpp, "AdaptationSet"));
// Pull up InbandEventStream elements defined in all child Representations.
for (int i = 0; i < commonRepresentationInbandEventStreams.size(); i++) {
InbandEventStream inbandEventStream = commonRepresentationInbandEventStreams.get(i);
if (!adaptationSetInbandEventStreams.contains(inbandEventStream)) {
adaptationSetInbandEventStreams.add(inbandEventStream);
}
}
// Build the representations.
List<Representation> representations = new ArrayList<>(representationInfos.size());
for (int i = 0; i < representationInfos.size(); i++) {
representations.add(buildRepresentation(representationInfos.get(i), contentId,
drmSchemeDatas));
}
return buildAdaptationSet(id, contentType, representations);
return buildAdaptationSet(id, contentType, representations, adaptationSetInbandEventStreams);
}
protected AdaptationSet buildAdaptationSet(int id, int contentType,
List<Representation> representations) {
return new AdaptationSet(id, contentType, representations);
List<Representation> representations, List<InbandEventStream> inbandEventStreams) {
return new AdaptationSet(id, contentType, representations, inbandEventStreams);
}
protected int parseContentType(XmlPullParser xpp) {
@ -355,6 +384,24 @@ public class DashManifestParser extends DefaultHandler
}
}
/**
* Parses an InbandEventStream 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 InbandEventStream} parsed from the element.
*/
protected InbandEventStream parseInbandEventStream(XmlPullParser xpp)
throws XmlPullParserException, IOException {
String schemeIdUri = parseString(xpp, "schemeIdUri", null);
String value = parseString(xpp, "value", null);
do {
xpp.next();
} while (!XmlPullParserUtil.isEndTag(xpp, "InbandEventStream"));
return new InbandEventStream(schemeIdUri, value);
}
/**
* Parses children of AdaptationSet elements not specifically parsed elsewhere.
*
@ -386,6 +433,7 @@ public class DashManifestParser extends DefaultHandler
int audioChannels = adaptationSetAudioChannels;
int audioSamplingRate = parseInt(xpp, "audioSamplingRate", adaptationSetAudioSamplingRate);
ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>();
ArrayList<InbandEventStream> inbandEventStreams = new ArrayList<>();
boolean seenFirstBaseUrl = false;
do {
@ -408,6 +456,8 @@ public class DashManifestParser extends DefaultHandler
if (contentProtection != null) {
drmSchemeDatas.add(contentProtection);
}
} else if (XmlPullParserUtil.isStartTag(xpp, "InbandEventStream")) {
inbandEventStreams.add(parseInbandEventStream(xpp));
}
} while (!XmlPullParserUtil.isEndTag(xpp, "Representation"));
@ -416,7 +466,7 @@ public class DashManifestParser extends DefaultHandler
codecs);
segmentBase = segmentBase != null ? segmentBase : new SingleSegmentBase();
return new RepresentationInfo(format, baseUrl, segmentBase, drmSchemeDatas);
return new RepresentationInfo(format, baseUrl, segmentBase, drmSchemeDatas, inbandEventStreams);
}
protected Format buildFormat(String id, String containerMimeType, int width, int height,
@ -850,13 +900,15 @@ public class DashManifestParser extends DefaultHandler
public final String baseUrl;
public final SegmentBase segmentBase;
public final ArrayList<SchemeData> drmSchemeDatas;
public final ArrayList<InbandEventStream> inbandEventStreams;
public RepresentationInfo(Format format, String baseUrl, SegmentBase segmentBase,
ArrayList<SchemeData> drmSchemeDatas) {
ArrayList<SchemeData> drmSchemeDatas, ArrayList<InbandEventStream> inbandEventStreams) {
this.format = format;
this.baseUrl = baseUrl;
this.segmentBase = segmentBase;
this.drmSchemeDatas = drmSchemeDatas;
this.inbandEventStreams = inbandEventStreams;
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.source.dash.manifest;
import com.google.android.exoplayer2.util.Util;
/**
* Represents a DASH in-band event stream.
*/
public class InbandEventStream {
public final String schemeIdUri;
public final String value;
public InbandEventStream(String schemeIdUri, String value) {
this.schemeIdUri = schemeIdUri;
this.value = value;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
InbandEventStream other = (InbandEventStream) obj;
return Util.areEqual(schemeIdUri, other.schemeIdUri) && Util.areEqual(value, other.value);
}
@Override
public int hashCode() {
return 31 * (schemeIdUri != null ? schemeIdUri.hashCode() : 0)
+ (value != null ? value.hashCode() : 0);
}
}