use of com.google.android.exoplayer2.source.SampleStream in project ExoPlayer by google.
the class ExtractorMediaPeriod method selectTracks.
@Override
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
Assertions.checkState(prepared);
// Disable 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;
sampleQueues.valueAt(track).disable();
streams[i] = null;
}
}
// Enable new tracks.
boolean selectedNewTracks = false;
for (int i = 0; i < selections.length; i++) {
if (streams[i] == null && selections[i] != null) {
TrackSelection 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;
selectedNewTracks = true;
}
}
if (!seenFirstTrackSelection) {
// At the time of the first track selection all queues will be enabled, so we need to disable
// any that are no longer required.
int trackCount = sampleQueues.size();
for (int i = 0; i < trackCount; i++) {
if (!trackEnabledStates[i]) {
sampleQueues.valueAt(i).disable();
}
}
}
if (enabledTrackCount == 0) {
notifyReset = false;
if (loader.isLoading()) {
loader.cancelLoading();
}
} else if (seenFirstTrackSelection ? selectedNewTracks : positionUs != 0) {
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 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();
}
}
}
}
}
use of com.google.android.exoplayer2.source.SampleStream in project ExoPlayer by google.
the class SsMediaPeriod method selectTracks.
@Override
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
ArrayList<ChunkSampleStream<SsChunkSource>> sampleStreamsList = new ArrayList<>();
for (int i = 0; i < selections.length; i++) {
if (streams[i] != null) {
@SuppressWarnings("unchecked") ChunkSampleStream<SsChunkSource> stream = (ChunkSampleStream<SsChunkSource>) streams[i];
if (selections[i] == null || !mayRetainStreamFlags[i]) {
stream.release();
streams[i] = null;
} else {
sampleStreamsList.add(stream);
}
}
if (streams[i] == null && selections[i] != null) {
ChunkSampleStream<SsChunkSource> stream = buildSampleStream(selections[i], positionUs);
sampleStreamsList.add(stream);
streams[i] = stream;
streamResetFlags[i] = true;
}
}
sampleStreams = newSampleStreamArray(sampleStreamsList.size());
sampleStreamsList.toArray(sampleStreams);
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
return positionUs;
}
use of com.google.android.exoplayer2.source.SampleStream in project ExoPlayer by google.
the class MediaCodecRenderer method readSourceOmittingSampleData.
/**
* Reads from the source when sample data is not required. If a format or an end of stream buffer
* is read, it will be handled before the call returns.
*
* @param readFlags Additional {@link ReadFlags}. {@link SampleStream#FLAG_OMIT_SAMPLE_DATA} is
* added internally, and so does not need to be passed.
* @return Whether a format was read and processed.
*/
private boolean readSourceOmittingSampleData(@SampleStream.ReadFlags int readFlags) throws ExoPlaybackException {
FormatHolder formatHolder = getFormatHolder();
noDataBuffer.clear();
@ReadDataResult int result = readSource(formatHolder, noDataBuffer, readFlags | FLAG_OMIT_SAMPLE_DATA);
if (result == C.RESULT_FORMAT_READ) {
onInputFormatChanged(formatHolder);
return true;
} else if (result == C.RESULT_BUFFER_READ && noDataBuffer.isEndOfStream()) {
inputStreamEnded = true;
processEndOfStream();
}
return false;
}
use of com.google.android.exoplayer2.source.SampleStream in project ExoPlayer by google.
the class ExoPlayerImplInternal method reselectTracksInternal.
private void reselectTracksInternal() throws ExoPlaybackException {
float playbackSpeed = mediaClock.getPlaybackParameters().speed;
// Reselect tracks on each period in turn, until the selection changes.
MediaPeriodHolder periodHolder = queue.getPlayingPeriod();
MediaPeriodHolder readingPeriodHolder = queue.getReadingPeriod();
boolean selectionsChangedForReadPeriod = true;
TrackSelectorResult newTrackSelectorResult;
while (true) {
if (periodHolder == null || !periodHolder.prepared) {
// The reselection did not change any prepared periods.
return;
}
newTrackSelectorResult = periodHolder.selectTracks(playbackSpeed, playbackInfo.timeline);
if (!newTrackSelectorResult.isEquivalent(periodHolder.getTrackSelectorResult())) {
// 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.getNext();
}
if (selectionsChangedForReadPeriod) {
// Update streams and rebuffer for the new selection, recreating all streams if reading ahead.
MediaPeriodHolder playingPeriodHolder = queue.getPlayingPeriod();
boolean recreateStreams = queue.removeAfter(playingPeriodHolder);
boolean[] streamResetFlags = new boolean[renderers.length];
long periodPositionUs = playingPeriodHolder.applyTrackSelection(newTrackSelectorResult, playbackInfo.positionUs, recreateStreams, streamResetFlags);
boolean hasDiscontinuity = playbackInfo.playbackState != Player.STATE_ENDED && periodPositionUs != playbackInfo.positionUs;
playbackInfo = handlePositionDiscontinuity(playbackInfo.periodId, periodPositionUs, playbackInfo.requestedContentPositionUs, playbackInfo.discontinuityStartPositionUs, hasDiscontinuity, Player.DISCONTINUITY_REASON_INTERNAL);
if (hasDiscontinuity) {
resetRendererPosition(periodPositionUs);
}
boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
for (int i = 0; i < renderers.length; i++) {
Renderer renderer = renderers[i];
rendererWasEnabledFlags[i] = isRendererEnabled(renderer);
SampleStream sampleStream = playingPeriodHolder.sampleStreams[i];
if (rendererWasEnabledFlags[i]) {
if (sampleStream != renderer.getStream()) {
// We need to disable the renderer.
disableRenderer(renderer);
} else if (streamResetFlags[i]) {
// The renderer will continue to consume from its current stream, but needs to be reset.
renderer.resetPosition(rendererPositionUs);
}
}
}
enableRenderers(rendererWasEnabledFlags);
} else {
// Release and re-prepare/buffer periods after the one whose selection changed.
queue.removeAfter(periodHolder);
if (periodHolder.prepared) {
long loadingPeriodPositionUs = max(periodHolder.info.startPositionUs, periodHolder.toPeriodTime(rendererPositionUs));
periodHolder.applyTrackSelection(newTrackSelectorResult, loadingPeriodPositionUs, false);
}
}
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */
true);
if (playbackInfo.playbackState != Player.STATE_ENDED) {
maybeContinueLoading();
updatePlaybackPositions();
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
}
}
Aggregations