From 5f6a7fc7f10134db7815e2f0c08e97fe427eedc3 Mon Sep 17 00:00:00 2001 From: sr1990 Date: Sat, 22 Jun 2019 18:56:06 -0700 Subject: [PATCH] [Patch V3] Support signalling of last segment number via supplemental descriptor in mpd. --- .../dash/manifest/DashManifestParser.java | 55 ++++++++++++++----- .../source/dash/manifest/SegmentBase.java | 9 ++- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java index 37230696f8..7e735e4844 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java @@ -242,7 +242,7 @@ public class DashManifestParser extends DefaultHandler } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentList")) { segmentBase = parseSegmentList(xpp, null); } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentTemplate")) { - segmentBase = parseSegmentTemplate(xpp, null,null); + segmentBase = parseSegmentTemplate(xpp, null,null,null); } else { maybeSkipTag(xpp); } @@ -333,7 +333,8 @@ public class DashManifestParser extends DefaultHandler } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentList")) { segmentBase = parseSegmentList(xpp, (SegmentList) segmentBase); } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentTemplate")) { - segmentBase = parseSegmentTemplate(xpp, (SegmentTemplate) segmentBase,supplementalProperties); + segmentBase = parseSegmentTemplate(xpp, (SegmentTemplate) segmentBase, + supplementalProperties,null); } else if (XmlPullParserUtil.isStartTag(xpp, "InbandEventStream")) { inbandEventStreams.add(parseDescriptor(xpp, "InbandEventStream")); } else if (XmlPullParserUtil.isStartTag(xpp)) { @@ -487,7 +488,7 @@ public class DashManifestParser extends DefaultHandler List adaptationSetRoleDescriptors, List adaptationSetAccessibilityDescriptors, SegmentBase segmentBase, - ArrayList parentSupplementalProperties) + ArrayList adaptationSetSupplementalProperties) throws XmlPullParserException, IOException { String id = xpp.getAttributeValue(null, "id"); int bandwidth = parseInt(xpp, "bandwidth", Format.NO_VALUE); @@ -520,7 +521,7 @@ public class DashManifestParser extends DefaultHandler segmentBase = parseSegmentList(xpp, (SegmentList) segmentBase); } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentTemplate")) { segmentBase = parseSegmentTemplate(xpp, (SegmentTemplate) segmentBase, - parentSupplementalProperties); + adaptationSetSupplementalProperties,supplementalProperties); } else if (XmlPullParserUtil.isStartTag(xpp, "ContentProtection")) { Pair contentProtection = parseContentProtection(xpp); if (contentProtection.first != null) { @@ -760,7 +761,8 @@ public class DashManifestParser extends DefaultHandler } protected SegmentTemplate parseSegmentTemplate(XmlPullParser xpp, SegmentTemplate parent, - ArrayList parentSupplementalProperties) + ArrayList adaptationSetSupplementalProperties, + ArrayList representationSupplementalProperties) throws XmlPullParserException, IOException { long timescale = parseLong(xpp, "timescale", parent != null ? parent.timescale : 1); long presentationTimeOffset = parseLong(xpp, "presentationTimeOffset", @@ -793,7 +795,18 @@ public class DashManifestParser extends DefaultHandler return buildSegmentTemplate(initialization, timescale, presentationTimeOffset, startNumber, duration, timeline, initializationTemplate, mediaTemplate, - parentSupplementalProperties); + adaptationSetSupplementalProperties,representationSupplementalProperties); + } + + protected String parseLastSegmentNumberSupplementalProperty + (List supplementalProperties){ + for (Descriptor descriptor : supplementalProperties) { + if (descriptor.schemeIdUri.equalsIgnoreCase + ("http://dashif.org/guidelines/last-segment-number")) { + return descriptor.value; + } + } + return null; } protected SegmentTemplate buildSegmentTemplate( @@ -804,16 +817,28 @@ public class DashManifestParser extends DefaultHandler long duration, List timeline, UrlTemplate initializationTemplate, - UrlTemplate mediaTemplate,ArrayList supplementalProperties ) { + UrlTemplate mediaTemplate,ArrayList adaptationSetSupplementalProperties, + ArrayList representationSupplementalProperties ) { - if (supplementalProperties != null) { - for (Descriptor descriptor : supplementalProperties) { - if (descriptor.schemeIdUri.equalsIgnoreCase - ("http://dashif.org/guidelines/last-segment-number")) { - return new SegmentTemplate(initialization, timescale, presentationTimeOffset, - startNumber, Integer.valueOf(descriptor.value),duration, timeline, - initializationTemplate, mediaTemplate); - } + if (representationSupplementalProperties != null) { + if (parseLastSegmentNumberSupplementalProperty + (representationSupplementalProperties) != null) { + String lastSegment = parseLastSegmentNumberSupplementalProperty + (representationSupplementalProperties); + return new SegmentTemplate(initialization, timescale, presentationTimeOffset, + startNumber, Integer.valueOf(lastSegment),duration, timeline, + initializationTemplate, mediaTemplate); + } + } + + if (adaptationSetSupplementalProperties != null) { + if (parseLastSegmentNumberSupplementalProperty(adaptationSetSupplementalProperties) != null) + { + String lastSegment = parseLastSegmentNumberSupplementalProperty + (adaptationSetSupplementalProperties); + return new SegmentTemplate(initialization, timescale, presentationTimeOffset, + startNumber, Integer.valueOf(lastSegment),duration, timeline, + initializationTemplate, mediaTemplate); } } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java index 720c20eed2..9eae69b345 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java @@ -140,7 +140,7 @@ public abstract class SegmentBase { * division of this value and {@code timescale}. * @param startNumber The sequence number of the first segment. * @param endNumber The sequence number of the last segment specified by SupplementalProperty - * schemeIdUri="http://dashif.org/guidelines/last-segment-number" + * schemeIdUri="http://dashif.org/guidelines/last-segment-number" * @param duration The duration of each segment in the case of fixed duration segments. The * value in seconds is the division of this value and {@code timescale}. If {@code * segmentTimeline} is non-null then this parameter is ignored. @@ -408,10 +408,10 @@ public abstract class SegmentBase { @Override public int getSegmentCount(long periodDurationUs) { - if( endNumber != C.INDEX_UNSET) { - return endNumber; - } else if (segmentTimeline != null) { + if (segmentTimeline != null) { return segmentTimeline.size(); + } else if (endNumber != C.INDEX_UNSET) { + return endNumber - (int) startNumber + 1; } else if (periodDurationUs != C.TIME_UNSET) { long durationUs = (duration * C.MICROS_PER_SECOND) / timescale; return (int) Util.ceilDivide(periodDurationUs, durationUs); @@ -419,7 +419,6 @@ public abstract class SegmentBase { return DashSegmentIndex.INDEX_UNBOUNDED; } } - } /**