added parsing for program information

parent 7849a5eb
...@@ -86,12 +86,17 @@ public class DashManifest implements FilterableManifest<DashManifest> { ...@@ -86,12 +86,17 @@ public class DashManifest implements FilterableManifest<DashManifest> {
*/ */
public final Uri location; public final Uri location;
/**
* The ProgramInformation of this manifest.
*/
public final ProgramInformation programInformation;
private final List<Period> periods; private final List<Period> periods;
public DashManifest(long availabilityStartTimeMs, long durationMs, long minBufferTimeMs, public DashManifest(long availabilityStartTimeMs, long durationMs, long minBufferTimeMs,
boolean dynamic, long minUpdatePeriodMs, long timeShiftBufferDepthMs, boolean dynamic, long minUpdatePeriodMs, long timeShiftBufferDepthMs,
long suggestedPresentationDelayMs, long publishTimeMs, UtcTimingElement utcTiming, long suggestedPresentationDelayMs, long publishTimeMs, UtcTimingElement utcTiming,
Uri location, List<Period> periods) { Uri location, ProgramInformation programInformation, List<Period> periods) {
this.availabilityStartTimeMs = availabilityStartTimeMs; this.availabilityStartTimeMs = availabilityStartTimeMs;
this.durationMs = durationMs; this.durationMs = durationMs;
this.minBufferTimeMs = minBufferTimeMs; this.minBufferTimeMs = minBufferTimeMs;
...@@ -102,6 +107,7 @@ public class DashManifest implements FilterableManifest<DashManifest> { ...@@ -102,6 +107,7 @@ public class DashManifest implements FilterableManifest<DashManifest> {
this.publishTimeMs = publishTimeMs; this.publishTimeMs = publishTimeMs;
this.utcTiming = utcTiming; this.utcTiming = utcTiming;
this.location = location; this.location = location;
this.programInformation = programInformation;
this.periods = periods == null ? Collections.emptyList() : periods; this.periods = periods == null ? Collections.emptyList() : periods;
} }
...@@ -150,7 +156,7 @@ public class DashManifest implements FilterableManifest<DashManifest> { ...@@ -150,7 +156,7 @@ public class DashManifest implements FilterableManifest<DashManifest> {
long newDuration = durationMs != C.TIME_UNSET ? durationMs - shiftMs : C.TIME_UNSET; long newDuration = durationMs != C.TIME_UNSET ? durationMs - shiftMs : C.TIME_UNSET;
return new DashManifest(availabilityStartTimeMs, newDuration, minBufferTimeMs, dynamic, return new DashManifest(availabilityStartTimeMs, newDuration, minBufferTimeMs, dynamic,
minUpdatePeriodMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs, publishTimeMs, minUpdatePeriodMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs, publishTimeMs,
utcTiming, location, copyPeriods); utcTiming, location, programInformation, copyPeriods);
} }
private static ArrayList<AdaptationSet> copyAdaptationSets( private static ArrayList<AdaptationSet> copyAdaptationSets(
......
...@@ -122,6 +122,7 @@ public class DashManifestParser extends DefaultHandler ...@@ -122,6 +122,7 @@ public class DashManifestParser extends DefaultHandler
long publishTimeMs = parseDateTime(xpp, "publishTime", C.TIME_UNSET); long publishTimeMs = parseDateTime(xpp, "publishTime", C.TIME_UNSET);
UtcTimingElement utcTiming = null; UtcTimingElement utcTiming = null;
Uri location = null; Uri location = null;
ProgramInformation programInformation = null;
List<Period> periods = new ArrayList<>(); List<Period> periods = new ArrayList<>();
long nextPeriodStartMs = dynamic ? C.TIME_UNSET : 0; long nextPeriodStartMs = dynamic ? C.TIME_UNSET : 0;
...@@ -138,6 +139,8 @@ public class DashManifestParser extends DefaultHandler ...@@ -138,6 +139,8 @@ public class DashManifestParser extends DefaultHandler
utcTiming = parseUtcTiming(xpp); utcTiming = parseUtcTiming(xpp);
} else if (XmlPullParserUtil.isStartTag(xpp, "Location")) { } else if (XmlPullParserUtil.isStartTag(xpp, "Location")) {
location = Uri.parse(xpp.nextText()); location = Uri.parse(xpp.nextText());
} else if (XmlPullParserUtil.isStartTag(xpp, "ProgramInformation")) {
programInformation = parseProgramInformation(xpp);
} else if (XmlPullParserUtil.isStartTag(xpp, "Period") && !seenEarlyAccessPeriod) { } else if (XmlPullParserUtil.isStartTag(xpp, "Period") && !seenEarlyAccessPeriod) {
Pair<Period, Long> periodWithDurationMs = parsePeriod(xpp, baseUrl, nextPeriodStartMs); Pair<Period, Long> periodWithDurationMs = parsePeriod(xpp, baseUrl, nextPeriodStartMs);
Period period = periodWithDurationMs.first; Period period = periodWithDurationMs.first;
...@@ -173,16 +176,16 @@ public class DashManifestParser extends DefaultHandler ...@@ -173,16 +176,16 @@ public class DashManifestParser extends DefaultHandler
return buildMediaPresentationDescription(availabilityStartTime, durationMs, minBufferTimeMs, return buildMediaPresentationDescription(availabilityStartTime, durationMs, minBufferTimeMs,
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs, dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs,
publishTimeMs, utcTiming, location, periods); publishTimeMs, utcTiming, location, programInformation, periods);
} }
protected DashManifest buildMediaPresentationDescription(long availabilityStartTime, protected DashManifest buildMediaPresentationDescription(long availabilityStartTime,
long durationMs, long minBufferTimeMs, boolean dynamic, long minUpdateTimeMs, long durationMs, long minBufferTimeMs, boolean dynamic, long minUpdateTimeMs,
long timeShiftBufferDepthMs, long suggestedPresentationDelayMs, long publishTimeMs, long timeShiftBufferDepthMs, long suggestedPresentationDelayMs, long publishTimeMs,
UtcTimingElement utcTiming, Uri location, List<Period> periods) { UtcTimingElement utcTiming, Uri location, ProgramInformation programInformation, List<Period> periods) {
return new DashManifest(availabilityStartTime, durationMs, minBufferTimeMs, return new DashManifest(availabilityStartTime, durationMs, minBufferTimeMs,
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs, dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs,
publishTimeMs, utcTiming, location, periods); publishTimeMs, utcTiming, location, programInformation, periods);
} }
protected UtcTimingElement parseUtcTiming(XmlPullParser xpp) { protected UtcTimingElement parseUtcTiming(XmlPullParser xpp) {
...@@ -978,6 +981,43 @@ public class DashManifestParser extends DefaultHandler ...@@ -978,6 +981,43 @@ public class DashManifestParser extends DefaultHandler
return new RangedUri(urlText, rangeStart, rangeLength); return new RangedUri(urlText, rangeStart, rangeLength);
} }
protected ProgramInformation parseProgramInformation(XmlPullParser xpp) throws IOException, XmlPullParserException {
String title = "";
String source = "";
String copyright = "";
List<byte[]> customEvents = new ArrayList<>();
do {
xpp.next();
if (XmlPullParserUtil.isStartTag(xpp, "Title")) {
title = xpp.getText();
} else if (XmlPullParserUtil.isStartTag(xpp, "Source")) {
source = xpp.getText();
} else if (XmlPullParserUtil.isStartTag(xpp, "Copyright")) {
copyright = xpp.getText();
} else {
byte[] customElement = parseCustomElement(xpp, new ByteArrayOutputStream(512));
if (customElement.length > 0) {
customEvents.add(customElement);
}
}
} while (!XmlPullParserUtil.isEndTag(xpp, "ProgramInformation"));
return new ProgramInformation(title, source, copyright, customEvents);
}
private byte[] parseCustomElement(XmlPullParser xpp, ByteArrayOutputStream outputStream) throws IOException, XmlPullParserException {
XmlSerializer serializer = Xml.newSerializer();
serializer.setOutput(outputStream, C.UTF8_NAME);
if (xpp.getEventType() == XmlPullParser.START_TAG) {
serializer.startTag(xpp.getNamespace(), xpp.getName());
for (int i = 0; i < xpp.getAttributeCount(); i++) {
serializer.attribute(xpp.getAttributeNamespace(i), xpp.getAttributeName(i), xpp.getAttributeValue(i));
}
serializer.endTag(xpp.getNamespace(), xpp.getName());
}
serializer.flush();
return outputStream.toByteArray();
}
// AudioChannelConfiguration parsing. // AudioChannelConfiguration parsing.
protected int parseAudioChannelConfiguration(XmlPullParser xpp) protected int parseAudioChannelConfiguration(XmlPullParser xpp)
......
package com.google.android.exoplayer2.source.dash.manifest;
import java.util.Arrays;
import java.util.List;
public class ProgramInformation {
/**
* The title for the media presentation.
*/
public final String title;
/**
* Information about the original source of the media presentation.
*/
public final String source;
/**
* A copyright statement for the media presentation.
*/
public final String copyright;
/**
* A list of custom elements.
*/
public final List<byte[]> customEvents;
public ProgramInformation(String title, String source, String copyright, List<byte[]> customEvents) {
this.title = title;
this.source = source;
this.copyright = copyright;
this.customEvents = customEvents;
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (source != null ? source.hashCode() : 0);
result = 31 * result + (copyright != null ? copyright.hashCode() : 0);
for (int i = 0; i < customEvents.size(); i++) {
result = 31 * result + Arrays.hashCode(customEvents.get(i));
}
return result;
}
@Override
public boolean equals(Object obj) {
return obj instanceof ProgramInformation
&& ((ProgramInformation)obj).title.equals(this.title)
&& ((ProgramInformation)obj).source.equals(this.source)
&& ((ProgramInformation)obj).copyright.equals(this.copyright)
&& validateEvents(((ProgramInformation)obj).customEvents);
}
private boolean validateEvents(List<byte[]> customEvents) {
for (int i = 0; i < customEvents.size() && i < this.customEvents.size(); i++) {
byte[] comparator = customEvents.get(i);
byte[] current = this.customEvents.get(i);
for (int j = 0; j < comparator.length && j < current.length; j++) {
if (current[j] != comparator[j]) {
return false;
}
}
}
return true;
}
}
\ No newline at end of file
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
xmlns="urn:mpeg:DASH:schema:MPD:2011" xmlns="urn:mpeg:DASH:schema:MPD:2011"
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd"
yt:earliestMediaSequence="1266404" > yt:earliestMediaSequence="1266404" >
<ProgramInformation>
<scte214:ContentIdentifier type="URN" value="5939026565177792163" />
</ProgramInformation>
<Period start="PT6462826.784S" > <Period start="PT6462826.784S" >
<SegmentList <SegmentList
presentationTimeOffset="34740095" presentationTimeOffset="34740095"
......
...@@ -25,6 +25,7 @@ import com.google.android.exoplayer2.testutil.TestUtil; ...@@ -25,6 +25,7 @@ import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.junit.Test; import org.junit.Test;
...@@ -153,6 +154,17 @@ public class DashManifestParserTest { ...@@ -153,6 +154,17 @@ public class DashManifestParserTest {
} }
@Test @Test
public void testParseMediaPresentationDescriptionCanParseProgramInformation() throws IOException {
DashManifestParser parser = new DashManifestParser();
DashManifest mpd = parser.parse(Uri.parse("Https://example.com/test.mpd"),
TestUtil.getInputStream(RuntimeEnvironment.application, SAMPLE_MPD_1));
List<byte[]> list = new ArrayList<>();
list.add("<scte214:ContentIdentifier type=\"URN\" value=\"5939026565177792163\" />".getBytes());
ProgramInformation programInformation = new ProgramInformation("", "", "", list);
assertThat(programInformation).isEqualTo(mpd.programInformation);
}
@Test
public void testParseCea608AccessibilityChannel() { public void testParseCea608AccessibilityChannel() {
assertThat( assertThat(
DashManifestParser.parseCea608AccessibilityChannel( DashManifestParser.parseCea608AccessibilityChannel(
......
...@@ -219,7 +219,7 @@ public class DashManifestTest { ...@@ -219,7 +219,7 @@ public class DashManifestTest {
private static DashManifest newDashManifest(int duration, Period... periods) { private static DashManifest newDashManifest(int duration, Period... periods) {
return new DashManifest( return new DashManifest(
0, duration, 1, false, 2, 3, 4, 12345, DUMMY_UTC_TIMING, Uri.EMPTY, Arrays.asList(periods)); 0, duration, 1, false, 2, 3, 4, 12345, DUMMY_UTC_TIMING, Uri.EMPTY, null, Arrays.asList(periods));
} }
private static Period newPeriod(String id, int startMs, AdaptationSet... adaptationSets) { private static Period newPeriod(String id, int startMs, AdaptationSet... adaptationSets) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment