Search in sources :

Example 6 with SampleStream

use of com.google.android.exoplayer2.source.SampleStream in project ExoPlayer by google.

the class ProgressiveMediaPeriod method selectTracks.

@Override
public long selectTracks(@NullableType ExoTrackSelection[] selections, boolean[] mayRetainStreamFlags, @NullableType SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
    assertPrepared();
    TrackGroupArray tracks = trackState.tracks;
    boolean[] trackEnabledStates = trackState.trackEnabledStates;
    int oldEnabledTrackCount = enabledTrackCount;
    // Deselect old tracks.
    for (int i = 0; i < selections.length; i++) {
        if (streams[i] != null && (selections[i] == null || !mayRetainStreamFlags[i])) {
            int track = ((SampleStreamImpl) streams[i]).track;
            Assertions.checkState(trackEnabledStates[track]);
            enabledTrackCount--;
            trackEnabledStates[track] = false;
            streams[i] = null;
        }
    }
    // We'll always need to seek if this is a first selection to a non-zero position, or if we're
    // making a selection having previously disabled all tracks.
    boolean seekRequired = seenFirstTrackSelection ? oldEnabledTrackCount == 0 : positionUs != 0;
    // Select new tracks.
    for (int i = 0; i < selections.length; i++) {
        if (streams[i] == null && selections[i] != null) {
            ExoTrackSelection selection = selections[i];
            Assertions.checkState(selection.length() == 1);
            Assertions.checkState(selection.getIndexInTrackGroup(0) == 0);
            int track = tracks.indexOf(selection.getTrackGroup());
            Assertions.checkState(!trackEnabledStates[track]);
            enabledTrackCount++;
            trackEnabledStates[track] = true;
            streams[i] = new SampleStreamImpl(track);
            streamResetFlags[i] = true;
            // If there's still a chance of avoiding a seek, try and seek within the sample queue.
            if (!seekRequired) {
                SampleQueue sampleQueue = sampleQueues[track];
                // A seek can be avoided if we're able to seek to the current playback position in the
                // sample queue, or if we haven't read anything from the queue since the previous seek
                // (this case is common for sparse tracks such as metadata tracks). In all other cases a
                // seek is required.
                seekRequired = !sampleQueue.seekTo(positionUs, /* allowTimeBeyondBuffer= */
                true) && sampleQueue.getReadIndex() != 0;
            }
        }
    }
    if (enabledTrackCount == 0) {
        pendingDeferredRetry = false;
        notifyDiscontinuity = false;
        if (loader.isLoading()) {
            // Discard as much as we can synchronously.
            for (SampleQueue sampleQueue : sampleQueues) {
                sampleQueue.discardToEnd();
            }
            loader.cancelLoading();
        } else {
            for (SampleQueue sampleQueue : sampleQueues) {
                sampleQueue.reset();
            }
        }
    } else if (seekRequired) {
        positionUs = seekToUs(positionUs);
        // We'll need to reset renderers consuming from all streams due to the seek.
        for (int i = 0; i < streams.length; i++) {
            if (streams[i] != null) {
                streamResetFlags[i] = true;
            }
        }
    }
    seenFirstTrackSelection = true;
    return positionUs;
}
Also used : ExoTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection)

Example 7 with SampleStream

use of com.google.android.exoplayer2.source.SampleStream in project ExoPlayer by google.

the class MergingMediaPeriodTest method selectTracks_createsSampleStreamsFromChildPeriods.

@Test
public void selectTracks_createsSampleStreamsFromChildPeriods() throws Exception {
    MergingMediaPeriod mergingMediaPeriod = prepareMergingPeriod(new MergingPeriodDefinition(/* timeOffsetUs= */
    0, /* singleSampleTimeUs= */
    0, childFormat11, childFormat12), new MergingPeriodDefinition(/* timeOffsetUs= */
    0, /* singleSampleTimeUs= */
    0, childFormat21, childFormat22));
    ExoTrackSelection selectionForChild1 = new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(1), /* track= */
    0);
    ExoTrackSelection selectionForChild2 = new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(2), /* track= */
    0);
    SampleStream[] streams = new SampleStream[4];
    mergingMediaPeriod.selectTracks(/* selections= */
    new ExoTrackSelection[] { null, selectionForChild1, selectionForChild2, null }, /* mayRetainStreamFlags= */
    new boolean[] { false, false, false, false }, streams, /* streamResetFlags= */
    new boolean[] { false, false, false, false }, /* positionUs= */
    0);
    mergingMediaPeriod.continueLoading(/* positionUs= */
    0);
    assertThat(streams[0]).isNull();
    assertThat(streams[3]).isNull();
    FormatHolder formatHolder = new FormatHolder();
    DecoderInputBuffer inputBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
    assertThat(streams[1].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT)).isEqualTo(C.RESULT_FORMAT_READ);
    assertThat(formatHolder.format).isEqualTo(childFormat12);
    assertThat(streams[2].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT)).isEqualTo(C.RESULT_FORMAT_READ);
    assertThat(formatHolder.format).isEqualTo(childFormat21);
}
Also used : ExoTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection) DecoderInputBuffer(com.google.android.exoplayer2.decoder.DecoderInputBuffer) FormatHolder(com.google.android.exoplayer2.FormatHolder) FixedTrackSelection(com.google.android.exoplayer2.trackselection.FixedTrackSelection) Test(org.junit.Test)

Example 8 with SampleStream

use of com.google.android.exoplayer2.source.SampleStream in project ExoPlayer by google.

the class DashMediaPeriod method selectNewStreams.

private void selectNewStreams(ExoTrackSelection[] selections, SampleStream[] streams, boolean[] streamResetFlags, long positionUs, int[] streamIndexToTrackGroupIndex) {
    // Create newly selected primary and event streams.
    for (int i = 0; i < selections.length; i++) {
        ExoTrackSelection selection = selections[i];
        if (selection == null) {
            continue;
        }
        if (streams[i] == null) {
            // Create new stream for selection.
            streamResetFlags[i] = true;
            int trackGroupIndex = streamIndexToTrackGroupIndex[i];
            TrackGroupInfo trackGroupInfo = trackGroupInfos[trackGroupIndex];
            if (trackGroupInfo.trackGroupCategory == TrackGroupInfo.CATEGORY_PRIMARY) {
                streams[i] = buildSampleStream(trackGroupInfo, selection, positionUs);
            } else if (trackGroupInfo.trackGroupCategory == TrackGroupInfo.CATEGORY_MANIFEST_EVENTS) {
                EventStream eventStream = eventStreams.get(trackGroupInfo.eventStreamGroupIndex);
                Format format = selection.getTrackGroup().getFormat(0);
                streams[i] = new EventSampleStream(eventStream, format, manifest.dynamic);
            }
        } else if (streams[i] instanceof ChunkSampleStream) {
            // Update selection in existing stream.
            @SuppressWarnings("unchecked") ChunkSampleStream<DashChunkSource> stream = (ChunkSampleStream<DashChunkSource>) streams[i];
            stream.getChunkSource().updateTrackSelection(selection);
        }
    }
    // pass if the index of the primary stream is greater than the index of the embedded stream.
    for (int i = 0; i < selections.length; i++) {
        if (streams[i] == null && selections[i] != null) {
            int trackGroupIndex = streamIndexToTrackGroupIndex[i];
            TrackGroupInfo trackGroupInfo = trackGroupInfos[trackGroupIndex];
            if (trackGroupInfo.trackGroupCategory == TrackGroupInfo.CATEGORY_EMBEDDED) {
                int primaryStreamIndex = getPrimaryStreamIndex(i, streamIndexToTrackGroupIndex);
                if (primaryStreamIndex == C.INDEX_UNSET) {
                    // If an embedded track is selected without the corresponding primary track, create an
                    // empty sample stream instead.
                    streams[i] = new EmptySampleStream();
                } else {
                    streams[i] = ((ChunkSampleStream) streams[primaryStreamIndex]).selectEmbeddedTrack(positionUs, trackGroupInfo.trackType);
                }
            }
        }
    }
}
Also used : Format(com.google.android.exoplayer2.Format) EmptySampleStream(com.google.android.exoplayer2.source.EmptySampleStream) ChunkSampleStream(com.google.android.exoplayer2.source.chunk.ChunkSampleStream) ExoTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection) EventStream(com.google.android.exoplayer2.source.dash.manifest.EventStream)

Example 9 with SampleStream

use of com.google.android.exoplayer2.source.SampleStream in project ExoPlayer by google.

the class DashMediaPeriod method updateManifest.

/**
 * Updates the {@link DashManifest} and the index of this period in the manifest.
 *
 * @param manifest The updated manifest.
 * @param periodIndex the new index of this period in the updated manifest.
 */
public void updateManifest(DashManifest manifest, int periodIndex) {
    this.manifest = manifest;
    this.periodIndex = periodIndex;
    playerEmsgHandler.updateManifest(manifest);
    if (sampleStreams != null) {
        for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
            sampleStream.getChunkSource().updateManifest(manifest, periodIndex);
        }
        callback.onContinueLoadingRequested(this);
    }
    eventStreams = manifest.getPeriod(periodIndex).eventStreams;
    for (EventSampleStream eventSampleStream : eventSampleStreams) {
        for (EventStream eventStream : eventStreams) {
            if (eventStream.id().equals(eventSampleStream.eventStreamId())) {
                int lastPeriodIndex = manifest.getPeriodCount() - 1;
                eventSampleStream.updateEventStream(eventStream, /* eventStreamAppendable= */
                manifest.dynamic && periodIndex == lastPeriodIndex);
                break;
            }
        }
    }
}
Also used : EventStream(com.google.android.exoplayer2.source.dash.manifest.EventStream)

Example 10 with SampleStream

use of com.google.android.exoplayer2.source.SampleStream in project ExoPlayer by google.

the class EventSampleStreamTest method seekToUsThenReadDataReturnDataFromSeekPosition.

/**
 * Tests that {@link EventSampleStream#seekToUs(long)} (long)} will seek to the given position,
 * and the next {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} call
 * will return sample data from that position.
 */
@Test
public void seekToUsThenReadDataReturnDataFromSeekPosition() {
    long presentationTimeUs1 = 1000000;
    long presentationTimeUs2 = 2000000;
    EventMessage eventMessage1 = newEventMessageWithId(1);
    EventMessage eventMessage2 = newEventMessageWithId(2);
    EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE, new long[] { presentationTimeUs1, presentationTimeUs2 }, new EventMessage[] { eventMessage1, eventMessage2 });
    EventSampleStream sampleStream = new EventSampleStream(eventStream, FORMAT, false);
    // first read - read format
    readData(sampleStream);
    sampleStream.seekToUs(presentationTimeUs2);
    int result = readData(sampleStream);
    assertThat(result).isEqualTo(C.RESULT_BUFFER_READ);
    assertThat(inputBuffer.data.array()).isEqualTo(getEncodedMessage(eventMessage2));
}
Also used : EventMessage(com.google.android.exoplayer2.metadata.emsg.EventMessage) EventStream(com.google.android.exoplayer2.source.dash.manifest.EventStream) Test(org.junit.Test)

Aggregations

EventStream (com.google.android.exoplayer2.source.dash.manifest.EventStream)15 Test (org.junit.Test)15 EventMessage (com.google.android.exoplayer2.metadata.emsg.EventMessage)10 ExoTrackSelection (com.google.android.exoplayer2.trackselection.ExoTrackSelection)10 SampleStream (com.google.android.exoplayer2.source.SampleStream)8 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)6 CompositeSequenceableLoader (com.google.android.exoplayer2.source.CompositeSequenceableLoader)5 ChunkSampleStream (com.google.android.exoplayer2.source.chunk.ChunkSampleStream)5 TrackSelection (com.google.android.exoplayer2.trackselection.TrackSelection)5 ArrayList (java.util.ArrayList)5 Format (com.google.android.exoplayer2.Format)3 FormatHolder (com.google.android.exoplayer2.FormatHolder)3 EmptySampleStream (com.google.android.exoplayer2.source.EmptySampleStream)3 TextRenderer (com.google.android.exoplayer2.text.TextRenderer)3 TrackSelectorResult (com.google.android.exoplayer2.trackselection.TrackSelectorResult)3 DecoderInputBuffer (com.google.android.exoplayer2.decoder.DecoderInputBuffer)2 SampleQueue (com.google.android.exoplayer2.source.SampleQueue)2 EmbeddedSampleStream (com.google.android.exoplayer2.source.chunk.ChunkSampleStream.EmbeddedSampleStream)2 FixedTrackSelection (com.google.android.exoplayer2.trackselection.FixedTrackSelection)2 NullableType (org.checkerframework.checker.nullness.compatqual.NullableType)2