Search in sources :

Example 1 with DashSegmentIndex

use of androidx.media3.exoplayer.dash.DashSegmentIndex in project media by androidx.

the class DashMediaSource method getAvailableStartTimeInManifestUs.

private static long getAvailableStartTimeInManifestUs(Period period, long periodDurationUs, long nowUnixTimeUs) {
    long periodStartTimeInManifestUs = Util.msToUs(period.startMs);
    long availableStartTimeInManifestUs = periodStartTimeInManifestUs;
    boolean haveAudioVideoAdaptationSets = hasVideoOrAudioAdaptationSets(period);
    for (int i = 0; i < period.adaptationSets.size(); i++) {
        AdaptationSet adaptationSet = period.adaptationSets.get(i);
        List<Representation> representations = adaptationSet.representations;
        // or video adaptation set. See: https://github.com/google/ExoPlayer/issues/4029
        if ((haveAudioVideoAdaptationSets && adaptationSet.type == C.TRACK_TYPE_TEXT) || representations.isEmpty()) {
            continue;
        }
        @Nullable DashSegmentIndex index = representations.get(0).getIndex();
        if (index == null) {
            return periodStartTimeInManifestUs;
        }
        long availableSegmentCount = index.getAvailableSegmentCount(periodDurationUs, nowUnixTimeUs);
        if (availableSegmentCount == 0) {
            return periodStartTimeInManifestUs;
        }
        long firstAvailableSegmentNum = index.getFirstAvailableSegmentNum(periodDurationUs, nowUnixTimeUs);
        long adaptationSetAvailableStartTimeInManifestUs = periodStartTimeInManifestUs + index.getTimeUs(firstAvailableSegmentNum);
        availableStartTimeInManifestUs = max(availableStartTimeInManifestUs, adaptationSetAvailableStartTimeInManifestUs);
    }
    return availableStartTimeInManifestUs;
}
Also used : AdaptationSet(androidx.media3.exoplayer.dash.manifest.AdaptationSet) Representation(androidx.media3.exoplayer.dash.manifest.Representation) Nullable(androidx.annotation.Nullable)

Example 2 with DashSegmentIndex

use of androidx.media3.exoplayer.dash.DashSegmentIndex in project media by androidx.

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)));
        }
    }
}
Also used : DownloadException(androidx.media3.exoplayer.offline.DownloadException) RangedUri(androidx.media3.exoplayer.dash.manifest.RangedUri) Representation(androidx.media3.exoplayer.dash.manifest.Representation) IOException(java.io.IOException) DashSegmentIndex(androidx.media3.exoplayer.dash.DashSegmentIndex) Nullable(androidx.annotation.Nullable)

Example 3 with DashSegmentIndex

use of androidx.media3.exoplayer.dash.DashSegmentIndex in project media by androidx.

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);
}
Also used : Period(androidx.media3.exoplayer.dash.manifest.Period) MediaPeriod(androidx.media3.exoplayer.source.MediaPeriod) Representation(androidx.media3.exoplayer.dash.manifest.Representation) Nullable(androidx.annotation.Nullable)

Example 4 with DashSegmentIndex

use of androidx.media3.exoplayer.dash.DashSegmentIndex in project media by androidx.

the class DashMediaSource method getAvailableEndTimeInManifestUs.

private static long getAvailableEndTimeInManifestUs(Period period, long periodDurationUs, long nowUnixTimeUs) {
    long periodStartTimeInManifestUs = Util.msToUs(period.startMs);
    long availableEndTimeInManifestUs = Long.MAX_VALUE;
    boolean haveAudioVideoAdaptationSets = hasVideoOrAudioAdaptationSets(period);
    for (int i = 0; i < period.adaptationSets.size(); i++) {
        AdaptationSet adaptationSet = period.adaptationSets.get(i);
        List<Representation> representations = adaptationSet.representations;
        // or video adaptation set. See: https://github.com/google/ExoPlayer/issues/4029
        if ((haveAudioVideoAdaptationSets && adaptationSet.type == C.TRACK_TYPE_TEXT) || representations.isEmpty()) {
            continue;
        }
        @Nullable DashSegmentIndex index = representations.get(0).getIndex();
        if (index == null) {
            return periodStartTimeInManifestUs + periodDurationUs;
        }
        long availableSegmentCount = index.getAvailableSegmentCount(periodDurationUs, nowUnixTimeUs);
        if (availableSegmentCount == 0) {
            return periodStartTimeInManifestUs;
        }
        long firstAvailableSegmentNum = index.getFirstAvailableSegmentNum(periodDurationUs, nowUnixTimeUs);
        long lastAvailableSegmentNum = firstAvailableSegmentNum + availableSegmentCount - 1;
        long adaptationSetAvailableEndTimeInManifestUs = periodStartTimeInManifestUs + index.getTimeUs(lastAvailableSegmentNum) + index.getDurationUs(lastAvailableSegmentNum, periodDurationUs);
        availableEndTimeInManifestUs = min(availableEndTimeInManifestUs, adaptationSetAvailableEndTimeInManifestUs);
    }
    return availableEndTimeInManifestUs;
}
Also used : AdaptationSet(androidx.media3.exoplayer.dash.manifest.AdaptationSet) Representation(androidx.media3.exoplayer.dash.manifest.Representation) Nullable(androidx.annotation.Nullable)

Example 5 with DashSegmentIndex

use of androidx.media3.exoplayer.dash.DashSegmentIndex in project media by androidx.

the class DashDownloader method getSegmentIndex.

@Nullable
private DashSegmentIndex getSegmentIndex(DataSource dataSource, int trackType, Representation representation, boolean removing) throws IOException, InterruptedException {
    DashSegmentIndex index = representation.getIndex();
    if (index != null) {
        return index;
    }
    RunnableFutureTask<@NullableType ChunkIndex, IOException> runnable = new RunnableFutureTask<@NullableType ChunkIndex, IOException>() {

        @Override
        @NullableType
        protected ChunkIndex doWork() throws IOException {
            return DashUtil.loadChunkIndex(dataSource, trackType, representation);
        }
    };
    @Nullable ChunkIndex seekMap = execute(runnable, removing);
    return seekMap == null ? null : new DashWrappingSegmentIndex(seekMap, representation.presentationTimeOffsetUs);
}
Also used : DashWrappingSegmentIndex(androidx.media3.exoplayer.dash.DashWrappingSegmentIndex) RunnableFutureTask(androidx.media3.common.util.RunnableFutureTask) IOException(java.io.IOException) NullableType(org.checkerframework.checker.nullness.compatqual.NullableType) DashSegmentIndex(androidx.media3.exoplayer.dash.DashSegmentIndex) ChunkIndex(androidx.media3.extractor.ChunkIndex) Nullable(androidx.annotation.Nullable) Nullable(androidx.annotation.Nullable)

Aggregations

Nullable (androidx.annotation.Nullable)5 Representation (androidx.media3.exoplayer.dash.manifest.Representation)4 DashSegmentIndex (androidx.media3.exoplayer.dash.DashSegmentIndex)2 AdaptationSet (androidx.media3.exoplayer.dash.manifest.AdaptationSet)2 IOException (java.io.IOException)2 RunnableFutureTask (androidx.media3.common.util.RunnableFutureTask)1 DashWrappingSegmentIndex (androidx.media3.exoplayer.dash.DashWrappingSegmentIndex)1 Period (androidx.media3.exoplayer.dash.manifest.Period)1 RangedUri (androidx.media3.exoplayer.dash.manifest.RangedUri)1 DownloadException (androidx.media3.exoplayer.offline.DownloadException)1 MediaPeriod (androidx.media3.exoplayer.source.MediaPeriod)1 ChunkIndex (androidx.media3.extractor.ChunkIndex)1 NullableType (org.checkerframework.checker.nullness.compatqual.NullableType)1