Search in sources :

Example 6 with Period

use of com.google.android.exoplayer2.source.dash.manifest.Period in project ExoPlayer by google.

the class ExoPlayerImplInternal method updatePeriods.

private void updatePeriods() throws ExoPlaybackException, IOException {
    if (timeline == null) {
        // We're waiting to get information about periods.
        mediaSource.maybeThrowSourceInfoRefreshError();
        return;
    }
    // Update the loading period if required.
    maybeUpdateLoadingPeriod();
    if (loadingPeriodHolder == null || loadingPeriodHolder.isFullyBuffered()) {
        setIsLoading(false);
    } else if (loadingPeriodHolder != null && loadingPeriodHolder.needsContinueLoading) {
        maybeContinueLoading();
    }
    if (playingPeriodHolder == null) {
        // We're waiting for the first period to be prepared.
        return;
    }
    // Update the playing and reading periods.
    while (playingPeriodHolder != readingPeriodHolder && rendererPositionUs >= playingPeriodHolder.next.rendererPositionOffsetUs) {
        // All enabled renderers' streams have been read to the end, and the playback position reached
        // the end of the playing period, so advance playback to the next period.
        playingPeriodHolder.release();
        setPlayingPeriodHolder(playingPeriodHolder.next);
        playbackInfo = new PlaybackInfo(playingPeriodHolder.index, playingPeriodHolder.startPositionUs);
        updatePlaybackPositions();
        eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, playbackInfo).sendToTarget();
    }
    if (readingPeriodHolder.isLast) {
        for (int i = 0; i < renderers.length; i++) {
            Renderer renderer = renderers[i];
            SampleStream sampleStream = readingPeriodHolder.sampleStreams[i];
            // stream in case of playlist changes that cause the stream to be no longer final.
            if (sampleStream != null && renderer.getStream() == sampleStream && renderer.hasReadStreamToEnd()) {
                renderer.setCurrentStreamFinal();
            }
        }
        return;
    }
    for (int i = 0; i < renderers.length; i++) {
        Renderer renderer = renderers[i];
        SampleStream sampleStream = readingPeriodHolder.sampleStreams[i];
        if (renderer.getStream() != sampleStream || (sampleStream != null && !renderer.hasReadStreamToEnd())) {
            return;
        }
    }
    if (readingPeriodHolder.next != null && readingPeriodHolder.next.prepared) {
        TrackSelectorResult oldTrackSelectorResult = readingPeriodHolder.trackSelectorResult;
        readingPeriodHolder = readingPeriodHolder.next;
        TrackSelectorResult newTrackSelectorResult = readingPeriodHolder.trackSelectorResult;
        boolean initialDiscontinuity = readingPeriodHolder.mediaPeriod.readDiscontinuity() != C.TIME_UNSET;
        for (int i = 0; i < renderers.length; i++) {
            Renderer renderer = renderers[i];
            TrackSelection oldSelection = oldTrackSelectorResult.selections.get(i);
            if (oldSelection == null) {
            // The renderer has no current stream and will be enabled when we play the next period.
            } else if (initialDiscontinuity) {
                // The new period starts with a discontinuity, so the renderer will play out all data then
                // be disabled and re-enabled when it starts playing the next period.
                renderer.setCurrentStreamFinal();
            } else if (!renderer.isCurrentStreamFinal()) {
                TrackSelection newSelection = newTrackSelectorResult.selections.get(i);
                RendererConfiguration oldConfig = oldTrackSelectorResult.rendererConfigurations[i];
                RendererConfiguration newConfig = newTrackSelectorResult.rendererConfigurations[i];
                if (newSelection != null && newConfig.equals(oldConfig)) {
                    // Replace the renderer's SampleStream so the transition to playing the next period can
                    // be seamless.
                    Format[] formats = new Format[newSelection.length()];
                    for (int j = 0; j < formats.length; j++) {
                        formats[j] = newSelection.getFormat(j);
                    }
                    renderer.replaceStream(formats, readingPeriodHolder.sampleStreams[i], readingPeriodHolder.getRendererOffset());
                } else {
                    // The renderer will be disabled when transitioning to playing the next period, either
                    // because there's no new selection or because a configuration change is required. Mark
                    // the SampleStream as final to play out any remaining data.
                    renderer.setCurrentStreamFinal();
                }
            }
        }
    }
}
Also used : TrackSelectorResult(com.google.android.exoplayer2.trackselection.TrackSelectorResult) TrackSelection(com.google.android.exoplayer2.trackselection.TrackSelection) SampleStream(com.google.android.exoplayer2.source.SampleStream)

Example 7 with Period

use of com.google.android.exoplayer2.source.dash.manifest.Period in project ExoPlayer by google.

the class ClippingMediaSourceTest method testClippingEnd.

public void testClippingEnd() {
    Timeline timeline = new SinglePeriodTimeline(C.msToUs(TEST_PERIOD_DURATION_US), true);
    Timeline clippedTimeline = getClippedTimeline(timeline, 0, TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US);
    assertEquals(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US, clippedTimeline.getWindow(0, window).getDurationUs());
    assertEquals(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US, clippedTimeline.getPeriod(0, period).getDurationUs());
}
Also used : Timeline(com.google.android.exoplayer2.Timeline)

Example 8 with Period

use of com.google.android.exoplayer2.source.dash.manifest.Period in project ExoPlayer by google.

the class DashManifestParser method parseMediaPresentationDescription.

protected DashManifest parseMediaPresentationDescription(XmlPullParser xpp, String baseUrl) throws XmlPullParserException, IOException {
    long availabilityStartTime = parseDateTime(xpp, "availabilityStartTime", C.TIME_UNSET);
    long durationMs = parseDuration(xpp, "mediaPresentationDuration", C.TIME_UNSET);
    long minBufferTimeMs = parseDuration(xpp, "minBufferTime", C.TIME_UNSET);
    String typeString = xpp.getAttributeValue(null, "type");
    boolean dynamic = typeString != null && typeString.equals("dynamic");
    long minUpdateTimeMs = dynamic ? parseDuration(xpp, "minimumUpdatePeriod", C.TIME_UNSET) : C.TIME_UNSET;
    long timeShiftBufferDepthMs = dynamic ? parseDuration(xpp, "timeShiftBufferDepth", C.TIME_UNSET) : C.TIME_UNSET;
    long suggestedPresentationDelayMs = dynamic ? parseDuration(xpp, "suggestedPresentationDelay", C.TIME_UNSET) : C.TIME_UNSET;
    UtcTimingElement utcTiming = null;
    Uri location = null;
    List<Period> periods = new ArrayList<>();
    long nextPeriodStartMs = dynamic ? C.TIME_UNSET : 0;
    boolean seenEarlyAccessPeriod = false;
    boolean seenFirstBaseUrl = false;
    do {
        xpp.next();
        if (XmlPullParserUtil.isStartTag(xpp, "BaseURL")) {
            if (!seenFirstBaseUrl) {
                baseUrl = parseBaseUrl(xpp, baseUrl);
                seenFirstBaseUrl = true;
            }
        } else if (XmlPullParserUtil.isStartTag(xpp, "UTCTiming")) {
            utcTiming = parseUtcTiming(xpp);
        } else if (XmlPullParserUtil.isStartTag(xpp, "Location")) {
            location = Uri.parse(xpp.nextText());
        } else if (XmlPullParserUtil.isStartTag(xpp, "Period") && !seenEarlyAccessPeriod) {
            Pair<Period, Long> periodWithDurationMs = parsePeriod(xpp, baseUrl, nextPeriodStartMs);
            Period period = periodWithDurationMs.first;
            if (period.startMs == C.TIME_UNSET) {
                if (dynamic) {
                    // This is an early access period. Ignore it. All subsequent periods must also be
                    // early access.
                    seenEarlyAccessPeriod = true;
                } else {
                    throw new ParserException("Unable to determine start of period " + periods.size());
                }
            } else {
                long periodDurationMs = periodWithDurationMs.second;
                nextPeriodStartMs = periodDurationMs == C.TIME_UNSET ? C.TIME_UNSET : (period.startMs + periodDurationMs);
                periods.add(period);
            }
        }
    } while (!XmlPullParserUtil.isEndTag(xpp, "MPD"));
    if (durationMs == C.TIME_UNSET) {
        if (nextPeriodStartMs != C.TIME_UNSET) {
            // If we know the end time of the final period, we can use it as the duration.
            durationMs = nextPeriodStartMs;
        } else if (!dynamic) {
            throw new ParserException("Unable to determine duration of static manifest.");
        }
    }
    if (periods.isEmpty()) {
        throw new ParserException("No periods found.");
    }
    return buildMediaPresentationDescription(availabilityStartTime, durationMs, minBufferTimeMs, dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs, utcTiming, location, periods);
}
Also used : ParserException(com.google.android.exoplayer2.ParserException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) ArrayList(java.util.ArrayList) Uri(android.net.Uri) Pair(android.util.Pair)

Example 9 with Period

use of com.google.android.exoplayer2.source.dash.manifest.Period in project ExoPlayer by google.

the class DashManifestParser method parsePeriod.

protected Pair<Period, Long> parsePeriod(XmlPullParser xpp, String baseUrl, long defaultStartMs) throws XmlPullParserException, IOException {
    String id = xpp.getAttributeValue(null, "id");
    long startMs = parseDuration(xpp, "start", defaultStartMs);
    long durationMs = parseDuration(xpp, "duration", C.TIME_UNSET);
    SegmentBase segmentBase = null;
    List<AdaptationSet> adaptationSets = new ArrayList<>();
    boolean seenFirstBaseUrl = false;
    do {
        xpp.next();
        if (XmlPullParserUtil.isStartTag(xpp, "BaseURL")) {
            if (!seenFirstBaseUrl) {
                baseUrl = parseBaseUrl(xpp, baseUrl);
                seenFirstBaseUrl = true;
            }
        } else if (XmlPullParserUtil.isStartTag(xpp, "AdaptationSet")) {
            adaptationSets.add(parseAdaptationSet(xpp, baseUrl, segmentBase));
        } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentBase")) {
            segmentBase = parseSegmentBase(xpp, null);
        } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentList")) {
            segmentBase = parseSegmentList(xpp, null);
        } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentTemplate")) {
            segmentBase = parseSegmentTemplate(xpp, null);
        }
    } while (!XmlPullParserUtil.isEndTag(xpp, "Period"));
    return Pair.create(buildPeriod(id, startMs, adaptationSets), durationMs);
}
Also used : SingleSegmentBase(com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase) ArrayList(java.util.ArrayList)

Example 10 with Period

use of com.google.android.exoplayer2.source.dash.manifest.Period in project ExoPlayer by google.

the class ClippingMediaSourceTest method testNoClipping.

public void testNoClipping() {
    Timeline timeline = new SinglePeriodTimeline(C.msToUs(TEST_PERIOD_DURATION_US), true);
    Timeline clippedTimeline = getClippedTimeline(timeline, 0, TEST_PERIOD_DURATION_US);
    assertEquals(1, clippedTimeline.getWindowCount());
    assertEquals(1, clippedTimeline.getPeriodCount());
    assertEquals(TEST_PERIOD_DURATION_US, clippedTimeline.getWindow(0, window).getDurationUs());
    assertEquals(TEST_PERIOD_DURATION_US, clippedTimeline.getPeriod(0, period).getDurationUs());
}
Also used : Timeline(com.google.android.exoplayer2.Timeline)

Aggregations

Timeline (com.google.android.exoplayer2.Timeline)5 SampleStream (com.google.android.exoplayer2.source.SampleStream)3 ArrayList (java.util.ArrayList)3 MediaSource (com.google.android.exoplayer2.source.MediaSource)2 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)2 TrackSelection (com.google.android.exoplayer2.trackselection.TrackSelection)2 Uri (android.net.Uri)1 Pair (android.util.Pair)1 Format (com.google.android.exoplayer2.Format)1 ParserException (com.google.android.exoplayer2.ParserException)1 Period (com.google.android.exoplayer2.Timeline.Period)1 Window (com.google.android.exoplayer2.Timeline.Window)1 CompositeSequenceableLoader (com.google.android.exoplayer2.source.CompositeSequenceableLoader)1 TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)1 AdaptationSet (com.google.android.exoplayer2.source.dash.manifest.AdaptationSet)1 Period (com.google.android.exoplayer2.source.dash.manifest.Period)1 Representation (com.google.android.exoplayer2.source.dash.manifest.Representation)1 SingleSegmentBase (com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase)1 TrackSelectorResult (com.google.android.exoplayer2.trackselection.TrackSelectorResult)1 XmlPullParserException (org.xmlpull.v1.XmlPullParserException)1