mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Parse some DASH manifest components for DVB LIVE.
This commit is contained in:
parent
5d35698d8f
commit
1ddd5c6e16
6 changed files with 95 additions and 35 deletions
|
|
@ -23,6 +23,8 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public final class MediaPresentationDescription {
|
public final class MediaPresentationDescription {
|
||||||
|
|
||||||
|
public final long availabilityStartTime;
|
||||||
|
|
||||||
public final long duration;
|
public final long duration;
|
||||||
|
|
||||||
public final long minBufferTime;
|
public final long minBufferTime;
|
||||||
|
|
@ -31,14 +33,22 @@ public final class MediaPresentationDescription {
|
||||||
|
|
||||||
public final long minUpdatePeriod;
|
public final long minUpdatePeriod;
|
||||||
|
|
||||||
|
public final long timeShiftBufferDepth;
|
||||||
|
|
||||||
public final List<Period> periods;
|
public final List<Period> periods;
|
||||||
|
|
||||||
public MediaPresentationDescription(long duration, long minBufferTime, boolean dynamic,
|
public final UtcTimingElement utcTiming;
|
||||||
long minUpdatePeriod, List<Period> periods) {
|
|
||||||
|
public MediaPresentationDescription(long availabilityStartTime, long duration, long minBufferTime,
|
||||||
|
boolean dynamic, long minUpdatePeriod, long timeShiftBufferDepth, UtcTimingElement utcTiming,
|
||||||
|
List<Period> periods) {
|
||||||
|
this.availabilityStartTime = availabilityStartTime;
|
||||||
this.duration = duration;
|
this.duration = duration;
|
||||||
this.minBufferTime = minBufferTime;
|
this.minBufferTime = minBufferTime;
|
||||||
this.dynamic = dynamic;
|
this.dynamic = dynamic;
|
||||||
this.minUpdatePeriod = minUpdatePeriod;
|
this.minUpdatePeriod = minUpdatePeriod;
|
||||||
|
this.timeShiftBufferDepth = timeShiftBufferDepth;
|
||||||
|
this.utcTiming = utcTiming;
|
||||||
this.periods = Collections.unmodifiableList(periods);
|
this.periods = Collections.unmodifiableList(periods);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@ import com.google.android.exoplayer.util.ManifestFetcher;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
|
@ -60,11 +58,7 @@ public final class MediaPresentationDescriptionFetcher extends
|
||||||
@Override
|
@Override
|
||||||
protected MediaPresentationDescription parse(InputStream stream, String inputEncoding,
|
protected MediaPresentationDescription parse(InputStream stream, String inputEncoding,
|
||||||
String contentId, Uri baseUrl) throws IOException, ParserException {
|
String contentId, Uri baseUrl) throws IOException, ParserException {
|
||||||
try {
|
return parser.parseMediaPresentationDescription(stream, inputEncoding, contentId, baseUrl);
|
||||||
return parser.parseMediaPresentationDescription(stream, inputEncoding, contentId, baseUrl);
|
|
||||||
} catch (XmlPullParserException e) {
|
|
||||||
throw new ParserException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,11 @@ import org.xmlpull.v1.XmlPullParserFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
@ -69,42 +72,57 @@ public class MediaPresentationDescriptionParser extends DefaultHandler {
|
||||||
* @param baseUrl The url that any relative urls defined within the manifest are relative to.
|
* @param baseUrl The url that any relative urls defined within the manifest are relative to.
|
||||||
* @return The parsed manifest.
|
* @return The parsed manifest.
|
||||||
* @throws IOException If a problem occurred reading from the stream.
|
* @throws IOException If a problem occurred reading from the stream.
|
||||||
* @throws XmlPullParserException If a problem occurred parsing the stream as xml.
|
|
||||||
* @throws ParserException If a problem occurred parsing the xml as a DASH mpd.
|
* @throws ParserException If a problem occurred parsing the xml as a DASH mpd.
|
||||||
*/
|
*/
|
||||||
public MediaPresentationDescription parseMediaPresentationDescription(InputStream inputStream,
|
public MediaPresentationDescription parseMediaPresentationDescription(InputStream inputStream,
|
||||||
String inputEncoding, String contentId, Uri baseUrl) throws XmlPullParserException,
|
String inputEncoding, String contentId, Uri baseUrl) throws IOException, ParserException {
|
||||||
IOException, ParserException {
|
try {
|
||||||
XmlPullParser xpp = xmlParserFactory.newPullParser();
|
XmlPullParser xpp = xmlParserFactory.newPullParser();
|
||||||
xpp.setInput(inputStream, inputEncoding);
|
xpp.setInput(inputStream, inputEncoding);
|
||||||
int eventType = xpp.next();
|
int eventType = xpp.next();
|
||||||
if (eventType != XmlPullParser.START_TAG || !"MPD".equals(xpp.getName())) {
|
if (eventType != XmlPullParser.START_TAG || !"MPD".equals(xpp.getName())) {
|
||||||
throw new ParserException(
|
throw new ParserException(
|
||||||
"inputStream does not contain a valid media presentation description");
|
"inputStream does not contain a valid media presentation description");
|
||||||
|
}
|
||||||
|
return parseMediaPresentationDescription(xpp, contentId, baseUrl);
|
||||||
|
} catch (XmlPullParserException e) {
|
||||||
|
throw new ParserException(e);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new ParserException(e);
|
||||||
}
|
}
|
||||||
return parseMediaPresentationDescription(xpp, contentId, baseUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private MediaPresentationDescription parseMediaPresentationDescription(XmlPullParser xpp,
|
private MediaPresentationDescription parseMediaPresentationDescription(XmlPullParser xpp,
|
||||||
String contentId, Uri baseUrl) throws XmlPullParserException, IOException {
|
String contentId, Uri baseUrl) throws XmlPullParserException, IOException, ParseException {
|
||||||
|
long availabilityStartTime = parseDateTime(xpp, "availabilityStartTime", -1);
|
||||||
long durationMs = parseDurationMs(xpp, "mediaPresentationDuration");
|
long durationMs = parseDurationMs(xpp, "mediaPresentationDuration");
|
||||||
long minBufferTimeMs = parseDurationMs(xpp, "minBufferTime");
|
long minBufferTimeMs = parseDurationMs(xpp, "minBufferTime");
|
||||||
String typeString = xpp.getAttributeValue(null, "type");
|
String typeString = xpp.getAttributeValue(null, "type");
|
||||||
boolean dynamic = (typeString != null) ? typeString.equals("dynamic") : false;
|
boolean dynamic = (typeString != null) ? typeString.equals("dynamic") : false;
|
||||||
long minUpdateTimeMs = (dynamic) ? parseDurationMs(xpp, "minimumUpdatePeriod", -1) : -1;
|
long minUpdateTimeMs = (dynamic) ? parseDurationMs(xpp, "minimumUpdatePeriod", -1) : -1;
|
||||||
|
long timeShiftBufferDepthMs = (dynamic) ? parseDurationMs(xpp, "timeShiftBufferDepth", -1) : -1;
|
||||||
|
UtcTimingElement utcTiming = null;
|
||||||
|
|
||||||
List<Period> periods = new ArrayList<Period>();
|
List<Period> periods = new ArrayList<Period>();
|
||||||
do {
|
do {
|
||||||
xpp.next();
|
xpp.next();
|
||||||
if (isStartTag(xpp, "BaseURL")) {
|
if (isStartTag(xpp, "BaseURL")) {
|
||||||
baseUrl = parseBaseUrl(xpp, baseUrl);
|
baseUrl = parseBaseUrl(xpp, baseUrl);
|
||||||
|
} else if (isStartTag(xpp, "UTCTiming")) {
|
||||||
|
utcTiming = parseUtcTiming(xpp);
|
||||||
} else if (isStartTag(xpp, "Period")) {
|
} else if (isStartTag(xpp, "Period")) {
|
||||||
periods.add(parsePeriod(xpp, contentId, baseUrl, durationMs));
|
periods.add(parsePeriod(xpp, contentId, baseUrl, durationMs));
|
||||||
}
|
}
|
||||||
} while (!isEndTag(xpp, "MPD"));
|
} while (!isEndTag(xpp, "MPD"));
|
||||||
|
|
||||||
return new MediaPresentationDescription(durationMs, minBufferTimeMs, dynamic, minUpdateTimeMs,
|
return new MediaPresentationDescription(availabilityStartTime, durationMs, minBufferTimeMs,
|
||||||
periods);
|
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, utcTiming, periods);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UtcTimingElement parseUtcTiming(XmlPullParser xpp) {
|
||||||
|
String schemeIdUri = xpp.getAttributeValue(null, "schemeIdUri");
|
||||||
|
String value = xpp.getAttributeValue(null, "value");
|
||||||
|
return new UtcTimingElement(schemeIdUri, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Period parsePeriod(XmlPullParser xpp, String contentId, Uri baseUrl, long mpdDurationMs)
|
private Period parsePeriod(XmlPullParser xpp, String contentId, Uri baseUrl, long mpdDurationMs)
|
||||||
|
|
@ -429,6 +447,16 @@ public class MediaPresentationDescriptionParser extends DefaultHandler {
|
||||||
return parseDurationMs(xpp, name, -1);
|
return parseDurationMs(xpp, name, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static long parseDateTime(XmlPullParser xpp, String name, long defaultValue)
|
||||||
|
throws ParseException {
|
||||||
|
String value = xpp.getAttributeValue(null, name);
|
||||||
|
if (value != null) {
|
||||||
|
SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-d'T'HH:mm:ss'Z'", Locale.US);
|
||||||
|
return parser.parse(value).getTime();
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
private static long parseDurationMs(XmlPullParser xpp, String name, long defaultValue) {
|
private static long parseDurationMs(XmlPullParser xpp, String name, long defaultValue) {
|
||||||
String value = xpp.getAttributeValue(null, name);
|
String value = xpp.getAttributeValue(null, name);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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.exoplayer.dash.mpd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a UTCTiming element.
|
||||||
|
*/
|
||||||
|
public class UtcTimingElement {
|
||||||
|
|
||||||
|
public final String schemeIdUri;
|
||||||
|
public final String value;
|
||||||
|
|
||||||
|
public UtcTimingElement(String schemeIdUri, String value) {
|
||||||
|
this.schemeIdUri = schemeIdUri;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -20,8 +20,6 @@ import com.google.android.exoplayer.util.ManifestFetcher;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
|
@ -59,11 +57,7 @@ public final class SmoothStreamingManifestFetcher extends ManifestFetcher<Smooth
|
||||||
@Override
|
@Override
|
||||||
protected SmoothStreamingManifest parse(InputStream stream, String inputEncoding,
|
protected SmoothStreamingManifest parse(InputStream stream, String inputEncoding,
|
||||||
String contentId, Uri baseUrl) throws IOException, ParserException {
|
String contentId, Uri baseUrl) throws IOException, ParserException {
|
||||||
try {
|
return parser.parse(stream, inputEncoding);
|
||||||
return parser.parse(stream, inputEncoding);
|
|
||||||
} catch (XmlPullParserException e) {
|
|
||||||
throw new ParserException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,15 +60,18 @@ public class SmoothStreamingManifestParser {
|
||||||
* @param inputEncoding The encoding of the input.
|
* @param inputEncoding The encoding of the input.
|
||||||
* @return The parsed manifest.
|
* @return The parsed manifest.
|
||||||
* @throws IOException If a problem occurred reading from the stream.
|
* @throws IOException If a problem occurred reading from the stream.
|
||||||
* @throws XmlPullParserException If a problem occurred parsing the stream as xml.
|
|
||||||
* @throws ParserException If a problem occurred parsing the xml as a smooth streaming manifest.
|
* @throws ParserException If a problem occurred parsing the xml as a smooth streaming manifest.
|
||||||
*/
|
*/
|
||||||
public SmoothStreamingManifest parse(InputStream inputStream, String inputEncoding) throws
|
public SmoothStreamingManifest parse(InputStream inputStream, String inputEncoding) throws
|
||||||
XmlPullParserException, IOException, ParserException {
|
IOException, ParserException {
|
||||||
XmlPullParser xmlParser = xmlParserFactory.newPullParser();
|
try {
|
||||||
xmlParser.setInput(inputStream, inputEncoding);
|
XmlPullParser xmlParser = xmlParserFactory.newPullParser();
|
||||||
SmoothStreamMediaParser smoothStreamMediaParser = new SmoothStreamMediaParser(null);
|
xmlParser.setInput(inputStream, inputEncoding);
|
||||||
return (SmoothStreamingManifest) smoothStreamMediaParser.parse(xmlParser);
|
SmoothStreamMediaParser smoothStreamMediaParser = new SmoothStreamMediaParser(null);
|
||||||
|
return (SmoothStreamingManifest) smoothStreamMediaParser.parse(xmlParser);
|
||||||
|
} catch (XmlPullParserException e) {
|
||||||
|
throw new ParserException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue