use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.
the class DashDownloader method addSegmentsForAdaptationSet.
private void addSegmentsForAdaptationSet(DataSource dataSource, AdaptationSet adaptationSet, long periodStartUs, long periodDurationUs, boolean removing, ArrayList<Segment> out) throws IOException, InterruptedException {
for (int i = 0; i < adaptationSet.representations.size(); i++) {
Representation representation = adaptationSet.representations.get(i);
DashSegmentIndex index;
try {
index = getSegmentIndex(dataSource, adaptationSet.type, representation, removing);
if (index == null) {
// Loading succeeded but there was no index.
throw new DownloadException("Missing segment index");
}
} catch (IOException e) {
if (!removing) {
throw e;
}
// Generating an incomplete segment list is allowed. Advance to the next representation.
continue;
}
long segmentCount = index.getSegmentCount(periodDurationUs);
if (segmentCount == DashSegmentIndex.INDEX_UNBOUNDED) {
throw new DownloadException("Unbounded segment index");
}
String baseUrl = castNonNull(baseUrlExclusionList.selectBaseUrl(representation.baseUrls)).url;
@Nullable RangedUri initializationUri = representation.getInitializationUri();
if (initializationUri != null) {
out.add(createSegment(representation, baseUrl, periodStartUs, initializationUri));
}
@Nullable RangedUri indexUri = representation.getIndexUri();
if (indexUri != null) {
out.add(createSegment(representation, baseUrl, periodStartUs, indexUri));
}
long firstSegmentNum = index.getFirstSegmentNum();
long lastSegmentNum = firstSegmentNum + segmentCount - 1;
for (long j = firstSegmentNum; j <= lastSegmentNum; j++) {
out.add(createSegment(representation, baseUrl, periodStartUs + index.getTimeUs(j), index.getSegmentUrl(j)));
}
}
}
use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.
the class DashManifestTest method copy.
@Test
public void copy() {
Representation[][][] representations = newRepresentations(3, 2, 3);
ServiceDescriptionElement serviceDescriptionElement = new ServiceDescriptionElement(/* targetOffsetMs= */
20, /* minOffsetMs= */
10, /* maxOffsetMs= */
40, /* minPlaybackSpeed= */
0.9f, /* maxPlaybackSpeed= */
1.1f);
DashManifest sourceManifest = newDashManifest(10, serviceDescriptionElement, newPeriod("1", 1, newAdaptationSet(2, representations[0][0]), newAdaptationSet(3, representations[0][1])), newPeriod("4", 4, newAdaptationSet(5, representations[1][0]), newAdaptationSet(6, representations[1][1])), newPeriod("7", 7, newAdaptationSet(8, representations[2][0]), newAdaptationSet(9, representations[2][1])));
List<StreamKey> keys = Arrays.asList(new StreamKey(0, 0, 0), new StreamKey(0, 0, 1), new StreamKey(0, 1, 2), new StreamKey(1, 0, 1), new StreamKey(1, 1, 0), new StreamKey(1, 1, 2), new StreamKey(2, 0, 1), new StreamKey(2, 0, 2), new StreamKey(2, 1, 0));
// Keys don't need to be in any particular order
Collections.shuffle(keys, new Random(0));
DashManifest copyManifest = sourceManifest.copy(keys);
DashManifest expectedManifest = newDashManifest(10, serviceDescriptionElement, newPeriod("1", 1, newAdaptationSet(2, representations[0][0][0], representations[0][0][1]), newAdaptationSet(3, representations[0][1][2])), newPeriod("4", 4, newAdaptationSet(5, representations[1][0][1]), newAdaptationSet(6, representations[1][1][0], representations[1][1][2])), newPeriod("7", 7, newAdaptationSet(8, representations[2][0][1], representations[2][0][2]), newAdaptationSet(9, representations[2][1][0])));
assertManifestEquals(expectedManifest, copyManifest);
}
use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.
the class DashManifestParserTest method parseMediaPresentationDescription_segmentTemplate.
@Test
public void parseMediaPresentationDescription_segmentTemplate() throws IOException {
DashManifestParser parser = new DashManifestParser();
DashManifest manifest = parser.parse(Uri.parse("https://example.com/test.mpd"), TestUtil.getInputStream(ApplicationProvider.getApplicationContext(), SAMPLE_MPD_SEGMENT_TEMPLATE));
assertThat(manifest.getPeriodCount()).isEqualTo(1);
Period period = manifest.getPeriod(0);
assertThat(period).isNotNull();
assertThat(period.adaptationSets).hasSize(2);
for (AdaptationSet adaptationSet : period.adaptationSets) {
assertThat(adaptationSet).isNotNull();
for (Representation representation : adaptationSet.representations) {
if (representation instanceof Representation.MultiSegmentRepresentation) {
Representation.MultiSegmentRepresentation multiSegmentRepresentation = (Representation.MultiSegmentRepresentation) representation;
long firstSegmentIndex = multiSegmentRepresentation.getFirstSegmentNum();
RangedUri uri = multiSegmentRepresentation.getSegmentUrl(firstSegmentIndex);
assertThat(uri.resolveUriString(representation.baseUrls.get(0).url)).contains("redirector.googlevideo.com");
}
}
}
}
use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.
the class DashManifestParserTest method getAvailabilityTimeOffsetUs.
private static long getAvailabilityTimeOffsetUs(AdaptationSet adaptationSet) {
assertThat(adaptationSet.representations).isNotEmpty();
Representation representation = adaptationSet.representations.get(0);
assertThat(representation).isInstanceOf(Representation.MultiSegmentRepresentation.class);
SegmentBase.MultiSegmentBase segmentBase = ((Representation.MultiSegmentRepresentation) representation).segmentBase;
return segmentBase.availabilityTimeOffsetUs;
}
use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.
the class DashMediaSource method getIntervalUntilNextManifestRefreshMs.
private static long getIntervalUntilNextManifestRefreshMs(DashManifest manifest, long nowUnixTimeMs) {
int periodIndex = manifest.getPeriodCount() - 1;
Period period = manifest.getPeriod(periodIndex);
long periodStartUs = Util.msToUs(period.startMs);
long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
long nowUnixTimeUs = Util.msToUs(nowUnixTimeMs);
long availabilityStartTimeUs = Util.msToUs(manifest.availabilityStartTimeMs);
long intervalUs = Util.msToUs(DEFAULT_NOTIFY_MANIFEST_INTERVAL_MS);
for (int i = 0; i < period.adaptationSets.size(); i++) {
List<Representation> representations = period.adaptationSets.get(i).representations;
if (representations.isEmpty()) {
continue;
}
@Nullable DashSegmentIndex index = representations.get(0).getIndex();
if (index != null) {
long nextSegmentShiftUnixTimeUs = availabilityStartTimeUs + periodStartUs + index.getNextSegmentAvailableTimeUs(periodDurationUs, nowUnixTimeUs);
long requiredIntervalUs = nextSegmentShiftUnixTimeUs - nowUnixTimeUs;
// Avoid multiple refreshes within a very small amount of time.
if (requiredIntervalUs < intervalUs - 100_000 || (requiredIntervalUs > intervalUs && requiredIntervalUs < intervalUs + 100_000)) {
intervalUs = requiredIntervalUs;
}
}
}
// Round up to compensate for a potential loss in the us to ms conversion.
return LongMath.divide(intervalUs, 1000, RoundingMode.CEILING);
}
Aggregations