Search in sources :

Example 1 with Period

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

the class ExoPlayerImplInternal method reselectTracksInternal.

private void reselectTracksInternal() throws ExoPlaybackException {
    if (playingPeriodHolder == null) {
        // We don't have tracks yet, so we don't care.
        return;
    }
    // Reselect tracks on each period in turn, until the selection changes.
    MediaPeriodHolder periodHolder = playingPeriodHolder;
    boolean selectionsChangedForReadPeriod = true;
    while (true) {
        if (periodHolder == null || !periodHolder.prepared) {
            // The reselection did not change any prepared periods.
            return;
        }
        if (periodHolder.selectTracks()) {
            // Selected tracks have changed for this period.
            break;
        }
        if (periodHolder == readingPeriodHolder) {
            // The track reselection didn't affect any period that has been read.
            selectionsChangedForReadPeriod = false;
        }
        periodHolder = periodHolder.next;
    }
    if (selectionsChangedForReadPeriod) {
        // Update streams and rebuffer for the new selection, recreating all streams if reading ahead.
        boolean recreateStreams = readingPeriodHolder != playingPeriodHolder;
        releasePeriodHoldersFrom(playingPeriodHolder.next);
        playingPeriodHolder.next = null;
        loadingPeriodHolder = playingPeriodHolder;
        readingPeriodHolder = playingPeriodHolder;
        boolean[] streamResetFlags = new boolean[renderers.length];
        long periodPositionUs = playingPeriodHolder.updatePeriodTrackSelection(playbackInfo.positionUs, recreateStreams, streamResetFlags);
        if (periodPositionUs != playbackInfo.positionUs) {
            playbackInfo.positionUs = periodPositionUs;
            resetRendererPosition(periodPositionUs);
        }
        int enabledRendererCount = 0;
        boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
        for (int i = 0; i < renderers.length; i++) {
            Renderer renderer = renderers[i];
            rendererWasEnabledFlags[i] = renderer.getState() != Renderer.STATE_DISABLED;
            SampleStream sampleStream = playingPeriodHolder.sampleStreams[i];
            if (sampleStream != null) {
                enabledRendererCount++;
            }
            if (rendererWasEnabledFlags[i]) {
                if (sampleStream != renderer.getStream()) {
                    // We need to disable the renderer.
                    if (renderer == rendererMediaClockSource) {
                        // The renderer is providing the media clock.
                        if (sampleStream == null) {
                            // The renderer won't be re-enabled. Sync standaloneMediaClock so that it can take
                            // over timing responsibilities.
                            standaloneMediaClock.setPositionUs(rendererMediaClock.getPositionUs());
                        }
                        rendererMediaClock = null;
                        rendererMediaClockSource = null;
                    }
                    ensureStopped(renderer);
                    renderer.disable();
                } else if (streamResetFlags[i]) {
                    // The renderer will continue to consume from its current stream, but needs to be reset.
                    renderer.resetPosition(rendererPositionUs);
                }
            }
        }
        eventHandler.obtainMessage(MSG_TRACKS_CHANGED, periodHolder.trackSelectorResult).sendToTarget();
        enableRenderers(rendererWasEnabledFlags, enabledRendererCount);
    } else {
        // Release and re-prepare/buffer periods after the one whose selection changed.
        loadingPeriodHolder = periodHolder;
        periodHolder = loadingPeriodHolder.next;
        while (periodHolder != null) {
            periodHolder.release();
            periodHolder = periodHolder.next;
        }
        loadingPeriodHolder.next = null;
        if (loadingPeriodHolder.prepared) {
            long loadingPeriodPositionUs = Math.max(loadingPeriodHolder.startPositionUs, loadingPeriodHolder.toPeriodTime(rendererPositionUs));
            loadingPeriodHolder.updatePeriodTrackSelection(loadingPeriodPositionUs, false);
        }
    }
    maybeContinueLoading();
    updatePlaybackPositions();
    handler.sendEmptyMessage(MSG_DO_SOME_WORK);
}
Also used : SampleStream(com.google.android.exoplayer2.source.SampleStream)

Example 2 with Period

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

the class OfflineLicenseHelper method download.

/**
   * Downloads an offline license.
   *
   * @param dataSource The {@link HttpDataSource} to be used for download.
   * @param dashManifest The {@link DashManifest} of the DASH content.
   * @return The downloaded offline license key set id.
   * @throws IOException If an error occurs reading data from the stream.
   * @throws InterruptedException If the thread has been interrupted.
   * @throws DrmSessionException Thrown when there is an error during DRM session.
   */
public byte[] download(HttpDataSource dataSource, DashManifest dashManifest) throws IOException, InterruptedException, DrmSessionException {
    // as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
    if (dashManifest.getPeriodCount() < 1) {
        return null;
    }
    Period period = dashManifest.getPeriod(0);
    int adaptationSetIndex = period.getAdaptationSetIndex(C.TRACK_TYPE_VIDEO);
    if (adaptationSetIndex == C.INDEX_UNSET) {
        adaptationSetIndex = period.getAdaptationSetIndex(C.TRACK_TYPE_AUDIO);
        if (adaptationSetIndex == C.INDEX_UNSET) {
            return null;
        }
    }
    AdaptationSet adaptationSet = period.adaptationSets.get(adaptationSetIndex);
    if (adaptationSet.representations.isEmpty()) {
        return null;
    }
    Representation representation = adaptationSet.representations.get(0);
    DrmInitData drmInitData = representation.format.drmInitData;
    if (drmInitData == null) {
        Format sampleFormat = DashUtil.loadSampleFormat(dataSource, representation);
        if (sampleFormat != null) {
            drmInitData = sampleFormat.drmInitData;
        }
        if (drmInitData == null) {
            return null;
        }
    }
    blockingKeyRequest(DefaultDrmSessionManager.MODE_DOWNLOAD, null, drmInitData);
    return drmSessionManager.getOfflineLicenseKeySetId();
}
Also used : Format(com.google.android.exoplayer2.Format) Period(com.google.android.exoplayer2.source.dash.manifest.Period) AdaptationSet(com.google.android.exoplayer2.source.dash.manifest.AdaptationSet) Representation(com.google.android.exoplayer2.source.dash.manifest.Representation)

Example 3 with Period

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

the class ClippingMediaSourceTest method testClippingStartAndEnd.

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

Example 4 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 5 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)

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