Parse ServiceDescription from DASH manifest
Issue: #4904 PiperOrigin-RevId: 336838559
This commit is contained in:
parent
d47258381f
commit
ed873322d3
@ -60,9 +60,10 @@ public final class C {
|
|||||||
*/
|
*/
|
||||||
public static final int POSITION_UNSET = -1;
|
public static final int POSITION_UNSET = -1;
|
||||||
|
|
||||||
/**
|
/** Represents an unset or unknown rate. */
|
||||||
* Represents an unset or unknown length.
|
public static final float RATE_UNSET = -Float.MAX_VALUE;
|
||||||
*/
|
|
||||||
|
/** Represents an unset or unknown length. */
|
||||||
public static final int LENGTH_UNSET = -1;
|
public static final int LENGTH_UNSET = -1;
|
||||||
|
|
||||||
/** Represents an unset or unknown percentage. */
|
/** Represents an unset or unknown percentage. */
|
||||||
|
@ -82,6 +82,9 @@ public class DashManifest implements FilterableManifest<DashManifest> {
|
|||||||
*/
|
*/
|
||||||
@Nullable public final UtcTimingElement utcTiming;
|
@Nullable public final UtcTimingElement utcTiming;
|
||||||
|
|
||||||
|
/** The {@link ServiceDescriptionElement}, or null if not present. */
|
||||||
|
@Nullable public final ServiceDescriptionElement serviceDescription;
|
||||||
|
|
||||||
/** The location of this manifest, or null if not present. */
|
/** The location of this manifest, or null if not present. */
|
||||||
@Nullable public final Uri location;
|
@Nullable public final Uri location;
|
||||||
|
|
||||||
@ -92,7 +95,7 @@ public class DashManifest implements FilterableManifest<DashManifest> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use {@link #DashManifest(long, long, long, boolean, long, long, long, long,
|
* @deprecated Use {@link #DashManifest(long, long, long, boolean, long, long, long, long,
|
||||||
* ProgramInformation, UtcTimingElement, Uri, List)}.
|
* ProgramInformation, UtcTimingElement, ServiceDescriptionElement, Uri, List)}.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public DashManifest(
|
public DashManifest(
|
||||||
@ -118,6 +121,7 @@ public class DashManifest implements FilterableManifest<DashManifest> {
|
|||||||
publishTimeMs,
|
publishTimeMs,
|
||||||
/* programInformation= */ null,
|
/* programInformation= */ null,
|
||||||
utcTiming,
|
utcTiming,
|
||||||
|
/* serviceDescription= */ null,
|
||||||
location,
|
location,
|
||||||
periods);
|
periods);
|
||||||
}
|
}
|
||||||
@ -133,6 +137,7 @@ public class DashManifest implements FilterableManifest<DashManifest> {
|
|||||||
long publishTimeMs,
|
long publishTimeMs,
|
||||||
@Nullable ProgramInformation programInformation,
|
@Nullable ProgramInformation programInformation,
|
||||||
@Nullable UtcTimingElement utcTiming,
|
@Nullable UtcTimingElement utcTiming,
|
||||||
|
@Nullable ServiceDescriptionElement serviceDescription,
|
||||||
@Nullable Uri location,
|
@Nullable Uri location,
|
||||||
List<Period> periods) {
|
List<Period> periods) {
|
||||||
this.availabilityStartTimeMs = availabilityStartTimeMs;
|
this.availabilityStartTimeMs = availabilityStartTimeMs;
|
||||||
@ -146,6 +151,7 @@ public class DashManifest implements FilterableManifest<DashManifest> {
|
|||||||
this.programInformation = programInformation;
|
this.programInformation = programInformation;
|
||||||
this.utcTiming = utcTiming;
|
this.utcTiming = utcTiming;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
|
this.serviceDescription = serviceDescription;
|
||||||
this.periods = periods == null ? Collections.emptyList() : periods;
|
this.periods = periods == null ? Collections.emptyList() : periods;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +209,7 @@ public class DashManifest implements FilterableManifest<DashManifest> {
|
|||||||
publishTimeMs,
|
publishTimeMs,
|
||||||
programInformation,
|
programInformation,
|
||||||
utcTiming,
|
utcTiming,
|
||||||
|
serviceDescription,
|
||||||
location,
|
location,
|
||||||
copyPeriods);
|
copyPeriods);
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,7 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
ProgramInformation programInformation = null;
|
ProgramInformation programInformation = null;
|
||||||
UtcTimingElement utcTiming = null;
|
UtcTimingElement utcTiming = null;
|
||||||
Uri location = null;
|
Uri location = null;
|
||||||
|
ServiceDescriptionElement serviceDescription = null;
|
||||||
long baseUrlAvailabilityTimeOffsetUs = dynamic ? 0 : C.TIME_UNSET;
|
long baseUrlAvailabilityTimeOffsetUs = dynamic ? 0 : C.TIME_UNSET;
|
||||||
|
|
||||||
List<Period> periods = new ArrayList<>();
|
List<Period> periods = new ArrayList<>();
|
||||||
@ -146,6 +147,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, "ServiceDescription")) {
|
||||||
|
serviceDescription = parseServiceDescription(xpp);
|
||||||
} else if (XmlPullParserUtil.isStartTag(xpp, "Period") && !seenEarlyAccessPeriod) {
|
} else if (XmlPullParserUtil.isStartTag(xpp, "Period") && !seenEarlyAccessPeriod) {
|
||||||
Pair<Period, Long> periodWithDurationMs =
|
Pair<Period, Long> periodWithDurationMs =
|
||||||
parsePeriod(
|
parsePeriod(
|
||||||
@ -199,6 +202,7 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
publishTimeMs,
|
publishTimeMs,
|
||||||
programInformation,
|
programInformation,
|
||||||
utcTiming,
|
utcTiming,
|
||||||
|
serviceDescription,
|
||||||
location,
|
location,
|
||||||
periods);
|
periods);
|
||||||
}
|
}
|
||||||
@ -214,6 +218,7 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
long publishTimeMs,
|
long publishTimeMs,
|
||||||
@Nullable ProgramInformation programInformation,
|
@Nullable ProgramInformation programInformation,
|
||||||
@Nullable UtcTimingElement utcTiming,
|
@Nullable UtcTimingElement utcTiming,
|
||||||
|
@Nullable ServiceDescriptionElement serviceDescription,
|
||||||
@Nullable Uri location,
|
@Nullable Uri location,
|
||||||
List<Period> periods) {
|
List<Period> periods) {
|
||||||
return new DashManifest(
|
return new DashManifest(
|
||||||
@ -227,6 +232,7 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
publishTimeMs,
|
publishTimeMs,
|
||||||
programInformation,
|
programInformation,
|
||||||
utcTiming,
|
utcTiming,
|
||||||
|
serviceDescription,
|
||||||
location,
|
location,
|
||||||
periods);
|
periods);
|
||||||
}
|
}
|
||||||
@ -241,6 +247,23 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
return new UtcTimingElement(schemeIdUri, value);
|
return new UtcTimingElement(schemeIdUri, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ServiceDescriptionElement parseServiceDescription(XmlPullParser xpp)
|
||||||
|
throws XmlPullParserException, IOException {
|
||||||
|
long targetOffsetMs = C.TIME_UNSET;
|
||||||
|
float minPlaybackSpeed = C.RATE_UNSET;
|
||||||
|
float maxPlaybackSpeed = C.RATE_UNSET;
|
||||||
|
do {
|
||||||
|
xpp.next();
|
||||||
|
if (XmlPullParserUtil.isStartTag(xpp, "Latency")) {
|
||||||
|
targetOffsetMs = parseLong(xpp, "target", C.TIME_UNSET);
|
||||||
|
} else if (XmlPullParserUtil.isStartTag(xpp, "PlaybackRate")) {
|
||||||
|
minPlaybackSpeed = parseFloat(xpp, "min", C.RATE_UNSET);
|
||||||
|
maxPlaybackSpeed = parseFloat(xpp, "max", C.RATE_UNSET);
|
||||||
|
}
|
||||||
|
} while (!XmlPullParserUtil.isEndTag(xpp, "ServiceDescription"));
|
||||||
|
return new ServiceDescriptionElement(targetOffsetMs, minPlaybackSpeed, maxPlaybackSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
protected Pair<Period, Long> parsePeriod(
|
protected Pair<Period, Long> parsePeriod(
|
||||||
XmlPullParser xpp,
|
XmlPullParser xpp,
|
||||||
String baseUrl,
|
String baseUrl,
|
||||||
@ -1715,6 +1738,11 @@ public class DashManifestParser extends DefaultHandler
|
|||||||
return value == null ? defaultValue : Long.parseLong(value);
|
return value == null ? defaultValue : Long.parseLong(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static float parseFloat(XmlPullParser xpp, String name, float defaultValue) {
|
||||||
|
String value = xpp.getAttributeValue(null, name);
|
||||||
|
return value == null ? defaultValue : Float.parseFloat(value);
|
||||||
|
}
|
||||||
|
|
||||||
protected static String parseString(XmlPullParser xpp, String name, String defaultValue) {
|
protected static String parseString(XmlPullParser xpp, String name, String defaultValue) {
|
||||||
String value = xpp.getAttributeValue(null, name);
|
String value = xpp.getAttributeValue(null, name);
|
||||||
return value == null ? defaultValue : value;
|
return value == null ? defaultValue : value;
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 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.C;
|
||||||
|
|
||||||
|
/** Represents a service description element. */
|
||||||
|
public final class ServiceDescriptionElement {
|
||||||
|
|
||||||
|
/** The target live offset in milliseconds, or {@link C#TIME_UNSET} if undefined. */
|
||||||
|
public final long targetOffsetMs;
|
||||||
|
/** The minimum playback speed for live speed adjustment, or {@link C#RATE_UNSET} if undefined. */
|
||||||
|
public final float minPlaybackSpeed;
|
||||||
|
/** The maximum playback speed for live speed adjustment, or {@link C#RATE_UNSET} if undefined. */
|
||||||
|
public final float maxPlaybackSpeed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a service description element.
|
||||||
|
*
|
||||||
|
* @param targetOffsetMs The target live offset in milliseconds, or {@link C#TIME_UNSET} if
|
||||||
|
* undefined.
|
||||||
|
* @param minPlaybackSpeed The minimum playback speed for live speed adjustment, or {@link
|
||||||
|
* C#RATE_UNSET} if undefined.
|
||||||
|
* @param maxPlaybackSpeed The maximum playback speed for live speed adjustment, or {@link
|
||||||
|
* C#RATE_UNSET} if undefined.
|
||||||
|
*/
|
||||||
|
public ServiceDescriptionElement(
|
||||||
|
long targetOffsetMs, float minPlaybackSpeed, float maxPlaybackSpeed) {
|
||||||
|
this.targetOffsetMs = targetOffsetMs;
|
||||||
|
this.minPlaybackSpeed = minPlaybackSpeed;
|
||||||
|
this.maxPlaybackSpeed = maxPlaybackSpeed;
|
||||||
|
}
|
||||||
|
}
|
@ -57,6 +57,12 @@ public class DashManifestParserTest {
|
|||||||
"media/mpd/sample_mpd_availabilityTimeOffset_segmentTemplate";
|
"media/mpd/sample_mpd_availabilityTimeOffset_segmentTemplate";
|
||||||
private static final String SAMPLE_MPD_AVAILABILITY_TIME_OFFSET_SEGMENT_LIST =
|
private static final String SAMPLE_MPD_AVAILABILITY_TIME_OFFSET_SEGMENT_LIST =
|
||||||
"media/mpd/sample_mpd_availabilityTimeOffset_segmentList";
|
"media/mpd/sample_mpd_availabilityTimeOffset_segmentList";
|
||||||
|
private static final String SAMPLE_MPD_SERVICE_DESCRIPTION_LOW_LATENCY =
|
||||||
|
"media/mpd/sample_mpd_service_description_low_latency";
|
||||||
|
private static final String SAMPLE_MPD_SERVICE_DESCRIPTION_LOW_LATENCY_NO_TARGET_LATENCY =
|
||||||
|
"media/mpd/sample_mpd_service_description_low_latency_no_target_latency";
|
||||||
|
private static final String SAMPLE_MPD_SERVICE_DESCRIPTION_LOW_LATENCY_NO_PLAYBACK_RATES =
|
||||||
|
"media/mpd/sample_mpd_service_description_low_latency_no_playback_rates";
|
||||||
|
|
||||||
private static final String NEXT_TAG_NAME = "Next";
|
private static final String NEXT_TAG_NAME = "Next";
|
||||||
private static final String NEXT_TAG = "<" + NEXT_TAG_NAME + "/>";
|
private static final String NEXT_TAG = "<" + NEXT_TAG_NAME + "/>";
|
||||||
@ -560,6 +566,71 @@ public class DashManifestParserTest {
|
|||||||
assertThat(getAvailabilityTimeOffsetUs(adaptationSets1.get(0))).isEqualTo(9_999_000);
|
assertThat(getAvailabilityTimeOffsetUs(adaptationSets1.get(0))).isEqualTo(9_999_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void serviceDescriptionElement_allValuesSet() throws IOException {
|
||||||
|
DashManifestParser parser = new DashManifestParser();
|
||||||
|
|
||||||
|
DashManifest manifest =
|
||||||
|
parser.parse(
|
||||||
|
Uri.parse("https://example.com/test.mpd"),
|
||||||
|
TestUtil.getInputStream(
|
||||||
|
ApplicationProvider.getApplicationContext(),
|
||||||
|
SAMPLE_MPD_SERVICE_DESCRIPTION_LOW_LATENCY));
|
||||||
|
|
||||||
|
assertThat(manifest.serviceDescription).isNotNull();
|
||||||
|
assertThat(manifest.serviceDescription.targetOffsetMs).isEqualTo(20_000);
|
||||||
|
assertThat(manifest.serviceDescription.minPlaybackSpeed).isEqualTo(0.1f);
|
||||||
|
assertThat(manifest.serviceDescription.maxPlaybackSpeed).isEqualTo(99f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void serviceDescriptionElement_noLatency_isUnset() throws IOException {
|
||||||
|
DashManifestParser parser = new DashManifestParser();
|
||||||
|
|
||||||
|
DashManifest manifest =
|
||||||
|
parser.parse(
|
||||||
|
Uri.parse("https://example.com/test.mpd"),
|
||||||
|
TestUtil.getInputStream(
|
||||||
|
ApplicationProvider.getApplicationContext(),
|
||||||
|
SAMPLE_MPD_SERVICE_DESCRIPTION_LOW_LATENCY_NO_TARGET_LATENCY));
|
||||||
|
|
||||||
|
assertThat(manifest.serviceDescription).isNotNull();
|
||||||
|
assertThat(manifest.serviceDescription.targetOffsetMs).isEqualTo(C.TIME_UNSET);
|
||||||
|
assertThat(manifest.serviceDescription.minPlaybackSpeed).isEqualTo(0.1f);
|
||||||
|
assertThat(manifest.serviceDescription.maxPlaybackSpeed).isEqualTo(99f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void serviceDescriptionElement_noPlaybackRates_isUnset() throws IOException {
|
||||||
|
DashManifestParser parser = new DashManifestParser();
|
||||||
|
|
||||||
|
DashManifest manifest =
|
||||||
|
parser.parse(
|
||||||
|
Uri.parse("https://example.com/test.mpd"),
|
||||||
|
TestUtil.getInputStream(
|
||||||
|
ApplicationProvider.getApplicationContext(),
|
||||||
|
SAMPLE_MPD_SERVICE_DESCRIPTION_LOW_LATENCY_NO_PLAYBACK_RATES));
|
||||||
|
|
||||||
|
assertThat(manifest.serviceDescription).isNotNull();
|
||||||
|
assertThat(manifest.serviceDescription.targetOffsetMs).isEqualTo(20_000);
|
||||||
|
assertThat(manifest.serviceDescription.minPlaybackSpeed).isEqualTo(C.RATE_UNSET);
|
||||||
|
assertThat(manifest.serviceDescription.maxPlaybackSpeed).isEqualTo(C.RATE_UNSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void serviceDescriptionElement_noServiceDescription_isNullInManifest() throws IOException {
|
||||||
|
DashManifestParser parser = new DashManifestParser();
|
||||||
|
|
||||||
|
DashManifest manifest =
|
||||||
|
parser.parse(
|
||||||
|
Uri.parse("https://example.com/test.mpd"),
|
||||||
|
TestUtil.getInputStream(
|
||||||
|
ApplicationProvider.getApplicationContext(),
|
||||||
|
SAMPLE_MPD_AVAILABILITY_TIME_OFFSET_SEGMENT_LIST));
|
||||||
|
|
||||||
|
assertThat(manifest.serviceDescription).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
private static List<Descriptor> buildCea608AccessibilityDescriptors(String value) {
|
private static List<Descriptor> buildCea608AccessibilityDescriptors(String value) {
|
||||||
return Collections.singletonList(new Descriptor("urn:scte:dash:cc:cea-608:2015", value, null));
|
return Collections.singletonList(new Descriptor("urn:scte:dash:cc:cea-608:2015", value, null));
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package com.google.android.exoplayer2.source.dash.manifest;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.offline.StreamKey;
|
import com.google.android.exoplayer2.offline.StreamKey;
|
||||||
@ -40,9 +41,13 @@ public class DashManifestTest {
|
|||||||
@Test
|
@Test
|
||||||
public void copy() {
|
public void copy() {
|
||||||
Representation[][][] representations = newRepresentations(3, 2, 3);
|
Representation[][][] representations = newRepresentations(3, 2, 3);
|
||||||
|
ServiceDescriptionElement serviceDescriptionElement =
|
||||||
|
new ServiceDescriptionElement(
|
||||||
|
/* targetOffsetMs= */ 20, /* minPlaybackSpeed= */ 0.9f, /* maxPlaybackSpeed= */ 1.1f);
|
||||||
DashManifest sourceManifest =
|
DashManifest sourceManifest =
|
||||||
newDashManifest(
|
newDashManifest(
|
||||||
10,
|
10,
|
||||||
|
serviceDescriptionElement,
|
||||||
newPeriod(
|
newPeriod(
|
||||||
"1",
|
"1",
|
||||||
1,
|
1,
|
||||||
@ -78,6 +83,7 @@ public class DashManifestTest {
|
|||||||
DashManifest expectedManifest =
|
DashManifest expectedManifest =
|
||||||
newDashManifest(
|
newDashManifest(
|
||||||
10,
|
10,
|
||||||
|
serviceDescriptionElement,
|
||||||
newPeriod(
|
newPeriod(
|
||||||
"1",
|
"1",
|
||||||
1,
|
1,
|
||||||
@ -102,6 +108,7 @@ public class DashManifestTest {
|
|||||||
DashManifest sourceManifest =
|
DashManifest sourceManifest =
|
||||||
newDashManifest(
|
newDashManifest(
|
||||||
10,
|
10,
|
||||||
|
/* serviceDescription= */ null,
|
||||||
newPeriod("1", 1, newAdaptationSet(2, representations[0][0])),
|
newPeriod("1", 1, newAdaptationSet(2, representations[0][0])),
|
||||||
newPeriod("4", 4, newAdaptationSet(5, representations[1][0])));
|
newPeriod("4", 4, newAdaptationSet(5, representations[1][0])));
|
||||||
|
|
||||||
@ -111,6 +118,7 @@ public class DashManifestTest {
|
|||||||
DashManifest expectedManifest =
|
DashManifest expectedManifest =
|
||||||
newDashManifest(
|
newDashManifest(
|
||||||
10,
|
10,
|
||||||
|
/* serviceDescription= */ null,
|
||||||
newPeriod("1", 1, newAdaptationSet(2, representations[0][0])),
|
newPeriod("1", 1, newAdaptationSet(2, representations[0][0])),
|
||||||
newPeriod("4", 4, newAdaptationSet(5, representations[1][0])));
|
newPeriod("4", 4, newAdaptationSet(5, representations[1][0])));
|
||||||
assertManifestEquals(expectedManifest, copyManifest);
|
assertManifestEquals(expectedManifest, copyManifest);
|
||||||
@ -122,6 +130,7 @@ public class DashManifestTest {
|
|||||||
DashManifest sourceManifest =
|
DashManifest sourceManifest =
|
||||||
newDashManifest(
|
newDashManifest(
|
||||||
10,
|
10,
|
||||||
|
/* serviceDescription= */ null,
|
||||||
newPeriod(
|
newPeriod(
|
||||||
"1",
|
"1",
|
||||||
1,
|
1,
|
||||||
@ -151,6 +160,7 @@ public class DashManifestTest {
|
|||||||
DashManifest expectedManifest =
|
DashManifest expectedManifest =
|
||||||
newDashManifest(
|
newDashManifest(
|
||||||
7,
|
7,
|
||||||
|
/* serviceDescription= */ null,
|
||||||
newPeriod(
|
newPeriod(
|
||||||
"1",
|
"1",
|
||||||
1,
|
1,
|
||||||
@ -177,6 +187,7 @@ public class DashManifestTest {
|
|||||||
assertThat(actual.utcTiming).isEqualTo(expected.utcTiming);
|
assertThat(actual.utcTiming).isEqualTo(expected.utcTiming);
|
||||||
assertThat(actual.location).isEqualTo(expected.location);
|
assertThat(actual.location).isEqualTo(expected.location);
|
||||||
assertThat(actual.getPeriodCount()).isEqualTo(expected.getPeriodCount());
|
assertThat(actual.getPeriodCount()).isEqualTo(expected.getPeriodCount());
|
||||||
|
assertThat(actual.serviceDescription).isEqualTo(expected.serviceDescription);
|
||||||
for (int i = 0; i < expected.getPeriodCount(); i++) {
|
for (int i = 0; i < expected.getPeriodCount(); i++) {
|
||||||
Period expectedPeriod = expected.getPeriod(i);
|
Period expectedPeriod = expected.getPeriod(i);
|
||||||
Period actualPeriod = actual.getPeriod(i);
|
Period actualPeriod = actual.getPeriod(i);
|
||||||
@ -217,7 +228,8 @@ public class DashManifestTest {
|
|||||||
return Representation.newInstance(/* revisionId= */ 0, FORMAT, /* baseUrl= */ "", SEGMENT_BASE);
|
return Representation.newInstance(/* revisionId= */ 0, FORMAT, /* baseUrl= */ "", SEGMENT_BASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DashManifest newDashManifest(int duration, Period... periods) {
|
private static DashManifest newDashManifest(
|
||||||
|
int duration, @Nullable ServiceDescriptionElement serviceDescription, Period... periods) {
|
||||||
return new DashManifest(
|
return new DashManifest(
|
||||||
/* availabilityStartTimeMs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
duration,
|
duration,
|
||||||
@ -229,6 +241,7 @@ public class DashManifestTest {
|
|||||||
/* publishTimeMs= */ 12345,
|
/* publishTimeMs= */ 12345,
|
||||||
/* programInformation= */ null,
|
/* programInformation= */ null,
|
||||||
UTC_TIMING,
|
UTC_TIMING,
|
||||||
|
serviceDescription,
|
||||||
Uri.EMPTY,
|
Uri.EMPTY,
|
||||||
Arrays.asList(periods));
|
Arrays.asList(periods));
|
||||||
}
|
}
|
||||||
|
14
testdata/src/test/assets/media/mpd/sample_mpd_service_description_low_latency
vendored
Normal file
14
testdata/src/test/assets/media/mpd/sample_mpd_service_description_low_latency
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<MPD type="static" duration="1s" mediaPresentationDuration="PT1S">
|
||||||
|
<ServiceDescription>
|
||||||
|
<Latency target="20000"/>
|
||||||
|
<PlaybackRate min="0.1" max="99"/>
|
||||||
|
</ServiceDescription>
|
||||||
|
<Period>
|
||||||
|
<AdaptationSet id="0" mimeType="audio/mp4" subsegmentAlignment="true">
|
||||||
|
<Representation id="0" codecs="mp4a.40.2" audioSamplingRate="48000" bandwidth="144000">
|
||||||
|
<BaseURL>https://test.com/0</BaseURL>
|
||||||
|
</Representation>
|
||||||
|
</AdaptationSet>
|
||||||
|
</Period>
|
||||||
|
</MPD>
|
13
testdata/src/test/assets/media/mpd/sample_mpd_service_description_low_latency_no_playback_rates
vendored
Normal file
13
testdata/src/test/assets/media/mpd/sample_mpd_service_description_low_latency_no_playback_rates
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<MPD type="static" duration="1s" mediaPresentationDuration="PT1S">
|
||||||
|
<ServiceDescription>
|
||||||
|
<Latency target="20000"/>
|
||||||
|
</ServiceDescription>
|
||||||
|
<Period>
|
||||||
|
<AdaptationSet id="0" mimeType="audio/mp4" subsegmentAlignment="true">
|
||||||
|
<Representation id="0" codecs="mp4a.40.2" audioSamplingRate="48000" bandwidth="144000">
|
||||||
|
<BaseURL>https://test.com/0</BaseURL>
|
||||||
|
</Representation>
|
||||||
|
</AdaptationSet>
|
||||||
|
</Period>
|
||||||
|
</MPD>
|
13
testdata/src/test/assets/media/mpd/sample_mpd_service_description_low_latency_no_target_latency
vendored
Normal file
13
testdata/src/test/assets/media/mpd/sample_mpd_service_description_low_latency_no_target_latency
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<MPD type="static" duration="1s" mediaPresentationDuration="PT1S">
|
||||||
|
<ServiceDescription>
|
||||||
|
<PlaybackRate min="0.1" max="99"/>
|
||||||
|
</ServiceDescription>
|
||||||
|
<Period>
|
||||||
|
<AdaptationSet id="0" mimeType="audio/mp4" subsegmentAlignment="true">
|
||||||
|
<Representation id="0" codecs="mp4a.40.2" audioSamplingRate="48000" bandwidth="144000">
|
||||||
|
<BaseURL>https://test.com/0</BaseURL>
|
||||||
|
</Representation>
|
||||||
|
</AdaptationSet>
|
||||||
|
</Period>
|
||||||
|
</MPD>
|
Loading…
x
Reference in New Issue
Block a user