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;
}
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);
}
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);
}
}
}
}
}
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;
}
}
}
}
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));
}
Aggregations