use of com.google.android.exoplayer2.source.SampleQueue in project ExoPlayer by google.
the class ProgressiveMediaPeriod method maybeFinishPrepare.
private void maybeFinishPrepare() {
if (released || prepared || !sampleQueuesBuilt || seekMap == null) {
return;
}
for (SampleQueue sampleQueue : sampleQueues) {
if (sampleQueue.getUpstreamFormat() == null) {
return;
}
}
loadCondition.close();
int trackCount = sampleQueues.length;
TrackGroup[] trackArray = new TrackGroup[trackCount];
boolean[] trackIsAudioVideoFlags = new boolean[trackCount];
for (int i = 0; i < trackCount; i++) {
Format trackFormat = Assertions.checkNotNull(sampleQueues[i].getUpstreamFormat());
@Nullable String mimeType = trackFormat.sampleMimeType;
boolean isAudio = MimeTypes.isAudio(mimeType);
boolean isAudioVideo = isAudio || MimeTypes.isVideo(mimeType);
trackIsAudioVideoFlags[i] = isAudioVideo;
haveAudioVideoTracks |= isAudioVideo;
@Nullable IcyHeaders icyHeaders = this.icyHeaders;
if (icyHeaders != null) {
if (isAudio || sampleQueueTrackIds[i].isIcyTrack) {
@Nullable Metadata metadata = trackFormat.metadata;
if (metadata == null) {
metadata = new Metadata(icyHeaders);
} else {
metadata = metadata.copyWithAppendedEntries(icyHeaders);
}
trackFormat = trackFormat.buildUpon().setMetadata(metadata).build();
}
// an average or peak bitrate of its own.
if (isAudio && trackFormat.averageBitrate == Format.NO_VALUE && trackFormat.peakBitrate == Format.NO_VALUE && icyHeaders.bitrate != Format.NO_VALUE) {
trackFormat = trackFormat.buildUpon().setAverageBitrate(icyHeaders.bitrate).build();
}
}
trackFormat = trackFormat.copyWithCryptoType(drmSessionManager.getCryptoType(trackFormat));
trackArray[i] = new TrackGroup(/* id= */
Integer.toString(i), trackFormat);
}
trackState = new TrackState(new TrackGroupArray(trackArray), trackIsAudioVideoFlags);
prepared = true;
Assertions.checkNotNull(callback).onPrepared(this);
}
use of com.google.android.exoplayer2.source.SampleQueue in project ExoPlayer by google.
the class ProgressiveMediaPeriod method onLoadCanceled.
@Override
public void onLoadCanceled(ExtractingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs, boolean released) {
StatsDataSource dataSource = loadable.dataSource;
LoadEventInfo loadEventInfo = new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, dataSource.getLastOpenedUri(), dataSource.getLastResponseHeaders(), elapsedRealtimeMs, loadDurationMs, dataSource.getBytesRead());
loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId);
mediaSourceEventDispatcher.loadCanceled(loadEventInfo, C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */
null, C.SELECTION_REASON_UNKNOWN, /* trackSelectionData= */
null, /* mediaStartTimeUs= */
loadable.seekTimeUs, durationUs);
if (!released) {
copyLengthFromLoader(loadable);
for (SampleQueue sampleQueue : sampleQueues) {
sampleQueue.reset();
}
if (enabledTrackCount > 0) {
Assertions.checkNotNull(callback).onContinueLoadingRequested(this);
}
}
}
use of com.google.android.exoplayer2.source.SampleQueue 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.SampleQueue in project ExoPlayer by google.
the class ChunkSampleStream method release.
/**
* Releases the stream.
*
* <p>This method should be called when the stream is no longer required. Either this method or
* {@link #release()} can be used to release this stream.
*
* @param callback An optional callback to be called on the loading thread once the loader has
* been released.
*/
public void release(@Nullable ReleaseCallback<T> callback) {
this.releaseCallback = callback;
// Discard as much as we can synchronously.
primarySampleQueue.preRelease();
for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) {
embeddedSampleQueue.preRelease();
}
loader.release(this);
}
use of com.google.android.exoplayer2.source.SampleQueue in project ExoPlayer by google.
the class ChunkSampleStream method continueLoading.
// SequenceableLoader implementation
@Override
public boolean continueLoading(long positionUs) {
if (loadingFinished || loader.isLoading() || loader.hasFatalError()) {
return false;
}
boolean pendingReset = isPendingReset();
List<BaseMediaChunk> chunkQueue;
long loadPositionUs;
if (pendingReset) {
chunkQueue = Collections.emptyList();
loadPositionUs = pendingResetPositionUs;
} else {
chunkQueue = readOnlyMediaChunks;
loadPositionUs = getLastMediaChunk().endTimeUs;
}
chunkSource.getNextChunk(positionUs, loadPositionUs, chunkQueue, nextChunkHolder);
boolean endOfStream = nextChunkHolder.endOfStream;
@Nullable Chunk loadable = nextChunkHolder.chunk;
nextChunkHolder.clear();
if (endOfStream) {
pendingResetPositionUs = C.TIME_UNSET;
loadingFinished = true;
return true;
}
if (loadable == null) {
return false;
}
loadingChunk = loadable;
if (isMediaChunk(loadable)) {
BaseMediaChunk mediaChunk = (BaseMediaChunk) loadable;
if (pendingReset) {
// even if its timestamp is slightly earlier than the advertised chunk start time.
if (mediaChunk.startTimeUs != pendingResetPositionUs) {
primarySampleQueue.setStartTimeUs(pendingResetPositionUs);
for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) {
embeddedSampleQueue.setStartTimeUs(pendingResetPositionUs);
}
}
pendingResetPositionUs = C.TIME_UNSET;
}
mediaChunk.init(chunkOutput);
mediaChunks.add(mediaChunk);
} else if (loadable instanceof InitializationChunk) {
((InitializationChunk) loadable).init(chunkOutput);
}
long elapsedRealtimeMs = loader.startLoading(loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(loadable.type));
mediaSourceEventDispatcher.loadStarted(new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs), loadable.type, primaryTrackType, loadable.trackFormat, loadable.trackSelectionReason, loadable.trackSelectionData, loadable.startTimeUs, loadable.endTimeUs);
return true;
}
Aggregations