mirror of
https://github.com/androidx/media.git
synced 2025-05-15 11:39:56 +08:00
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:
parent
21762622ac
commit
44d6b1a271
@ -23,18 +23,48 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class AdaptationSet {
|
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;
|
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;
|
public final int type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Representation}s in the adaptation set.
|
||||||
|
*/
|
||||||
public final List<Representation> representations;
|
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.id = id;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.representations = Collections.unmodifiableList(representations);
|
this.representations = Collections.unmodifiableList(representations);
|
||||||
|
this.inbandEventStreams = Collections.unmodifiableList(inbandEventStreams);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
|
|
||||||
protected AdaptationSet parseAdaptationSet(XmlPullParser xpp, String baseUrl,
|
protected AdaptationSet parseAdaptationSet(XmlPullParser xpp, String baseUrl,
|
||||||
SegmentBase segmentBase) throws XmlPullParserException, IOException {
|
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);
|
int contentType = parseContentType(xpp);
|
||||||
|
|
||||||
String mimeType = xpp.getAttributeValue(null, "mimeType");
|
String mimeType = xpp.getAttributeValue(null, "mimeType");
|
||||||
@ -241,6 +241,8 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
int accessibilityChannel = Format.NO_VALUE;
|
int accessibilityChannel = Format.NO_VALUE;
|
||||||
ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>();
|
ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>();
|
||||||
List<RepresentationInfo> representationInfos = new ArrayList<>();
|
List<RepresentationInfo> representationInfos = new ArrayList<>();
|
||||||
|
List<InbandEventStream> adaptationSetInbandEventStreams = new ArrayList<>();
|
||||||
|
List<InbandEventStream> commonRepresentationInbandEventStreams = null;
|
||||||
|
|
||||||
boolean seenFirstBaseUrl = false;
|
boolean seenFirstBaseUrl = false;
|
||||||
do {
|
do {
|
||||||
@ -265,6 +267,22 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
contentType = checkContentTypeConsistency(contentType,
|
contentType = checkContentTypeConsistency(contentType,
|
||||||
getContentType(representationInfo.format));
|
getContentType(representationInfo.format));
|
||||||
representationInfos.add(representationInfo);
|
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")) {
|
} else if (XmlPullParserUtil.isStartTag(xpp, "AudioChannelConfiguration")) {
|
||||||
audioChannels = parseAudioChannelConfiguration(xpp);
|
audioChannels = parseAudioChannelConfiguration(xpp);
|
||||||
} else if (XmlPullParserUtil.isStartTag(xpp, "Accessibility")) {
|
} else if (XmlPullParserUtil.isStartTag(xpp, "Accessibility")) {
|
||||||
@ -275,23 +293,34 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
segmentBase = parseSegmentList(xpp, (SegmentList) segmentBase);
|
segmentBase = parseSegmentList(xpp, (SegmentList) segmentBase);
|
||||||
} else if (XmlPullParserUtil.isStartTag(xpp, "SegmentTemplate")) {
|
} else if (XmlPullParserUtil.isStartTag(xpp, "SegmentTemplate")) {
|
||||||
segmentBase = parseSegmentTemplate(xpp, (SegmentTemplate) segmentBase);
|
segmentBase = parseSegmentTemplate(xpp, (SegmentTemplate) segmentBase);
|
||||||
|
} else if (XmlPullParserUtil.isStartTag(xpp, "InbandEventStream")) {
|
||||||
|
adaptationSetInbandEventStreams.add(parseInbandEventStream(xpp));
|
||||||
} else if (XmlPullParserUtil.isStartTag(xpp)) {
|
} else if (XmlPullParserUtil.isStartTag(xpp)) {
|
||||||
parseAdaptationSetChild(xpp);
|
parseAdaptationSetChild(xpp);
|
||||||
}
|
}
|
||||||
} while (!XmlPullParserUtil.isEndTag(xpp, "AdaptationSet"));
|
} 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());
|
List<Representation> representations = new ArrayList<>(representationInfos.size());
|
||||||
for (int i = 0; i < representationInfos.size(); i++) {
|
for (int i = 0; i < representationInfos.size(); i++) {
|
||||||
representations.add(buildRepresentation(representationInfos.get(i), contentId,
|
representations.add(buildRepresentation(representationInfos.get(i), contentId,
|
||||||
drmSchemeDatas));
|
drmSchemeDatas));
|
||||||
}
|
}
|
||||||
|
|
||||||
return buildAdaptationSet(id, contentType, representations);
|
return buildAdaptationSet(id, contentType, representations, adaptationSetInbandEventStreams);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AdaptationSet buildAdaptationSet(int id, int contentType,
|
protected AdaptationSet buildAdaptationSet(int id, int contentType,
|
||||||
List<Representation> representations) {
|
List<Representation> representations, List<InbandEventStream> inbandEventStreams) {
|
||||||
return new AdaptationSet(id, contentType, representations);
|
return new AdaptationSet(id, contentType, representations, inbandEventStreams);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int parseContentType(XmlPullParser xpp) {
|
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.
|
* Parses children of AdaptationSet elements not specifically parsed elsewhere.
|
||||||
*
|
*
|
||||||
@ -386,6 +433,7 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
int audioChannels = adaptationSetAudioChannels;
|
int audioChannels = adaptationSetAudioChannels;
|
||||||
int audioSamplingRate = parseInt(xpp, "audioSamplingRate", adaptationSetAudioSamplingRate);
|
int audioSamplingRate = parseInt(xpp, "audioSamplingRate", adaptationSetAudioSamplingRate);
|
||||||
ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>();
|
ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>();
|
||||||
|
ArrayList<InbandEventStream> inbandEventStreams = new ArrayList<>();
|
||||||
|
|
||||||
boolean seenFirstBaseUrl = false;
|
boolean seenFirstBaseUrl = false;
|
||||||
do {
|
do {
|
||||||
@ -408,6 +456,8 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
if (contentProtection != null) {
|
if (contentProtection != null) {
|
||||||
drmSchemeDatas.add(contentProtection);
|
drmSchemeDatas.add(contentProtection);
|
||||||
}
|
}
|
||||||
|
} else if (XmlPullParserUtil.isStartTag(xpp, "InbandEventStream")) {
|
||||||
|
inbandEventStreams.add(parseInbandEventStream(xpp));
|
||||||
}
|
}
|
||||||
} while (!XmlPullParserUtil.isEndTag(xpp, "Representation"));
|
} while (!XmlPullParserUtil.isEndTag(xpp, "Representation"));
|
||||||
|
|
||||||
@ -416,7 +466,7 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
codecs);
|
codecs);
|
||||||
segmentBase = segmentBase != null ? segmentBase : new SingleSegmentBase();
|
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,
|
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 String baseUrl;
|
||||||
public final SegmentBase segmentBase;
|
public final SegmentBase segmentBase;
|
||||||
public final ArrayList<SchemeData> drmSchemeDatas;
|
public final ArrayList<SchemeData> drmSchemeDatas;
|
||||||
|
public final ArrayList<InbandEventStream> inbandEventStreams;
|
||||||
|
|
||||||
public RepresentationInfo(Format format, String baseUrl, SegmentBase segmentBase,
|
public RepresentationInfo(Format format, String baseUrl, SegmentBase segmentBase,
|
||||||
ArrayList<SchemeData> drmSchemeDatas) {
|
ArrayList<SchemeData> drmSchemeDatas, ArrayList<InbandEventStream> inbandEventStreams) {
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
this.segmentBase = segmentBase;
|
this.segmentBase = segmentBase;
|
||||||
this.drmSchemeDatas = drmSchemeDatas;
|
this.drmSchemeDatas = drmSchemeDatas;
|
||||||
|
this.inbandEventStreams = inbandEventStreams;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user