use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.
the class ExtractorAsserts method assertOutput.
/**
* Asserts that an extractor consumes valid input data successfully under the specified
* conditions.
*
* @param extractor The {@link Extractor} to be tested.
* @param dumpFilesPrefix The dump files prefix prepended to the dump files path.
* @param data Content of the input file.
* @param context To be used to load the sample file.
* @param sniffFirst Whether to sniff the data by calling {@link Extractor#sniff(ExtractorInput)}
* prior to consuming it.
* @param simulateIOErrors Whether to simulate IO errors.
* @param simulateUnknownLength Whether to simulate unknown input length.
* @param simulatePartialReads Whether to simulate partial reads.
* @throws IOException If reading from the input fails.
*/
private static void assertOutput(Extractor extractor, String dumpFilesPrefix, byte[] data, Context context, boolean deduplicateConsecutiveFormats, boolean sniffFirst, boolean simulateIOErrors, boolean simulateUnknownLength, boolean simulatePartialReads) throws IOException {
FakeExtractorInput input = new FakeExtractorInput.Builder().setData(data).setSimulateIOErrors(simulateIOErrors).setSimulateUnknownLength(simulateUnknownLength).setSimulatePartialReads(simulatePartialReads).build();
if (sniffFirst) {
assertSniff(extractor, input, /* expectedResult= */
true);
input.resetPeekPosition();
}
FakeExtractorOutput extractorOutput = consumeTestData(extractor, input, 0, true, deduplicateConsecutiveFormats);
if (simulateUnknownLength) {
DumpFileAsserts.assertOutput(context, extractorOutput, dumpFilesPrefix + UNKNOWN_LENGTH_EXTENSION);
} else {
DumpFileAsserts.assertOutput(context, extractorOutput, dumpFilesPrefix + ".0" + DUMP_EXTENSION);
}
// Seeking to (timeUs=0, position=0) should always work, and cause the same data to be output.
extractorOutput.clearTrackOutputs();
input.reset();
consumeTestData(extractor, input, /* timeUs= */
0, extractorOutput, false);
if (simulateUnknownLength) {
DumpFileAsserts.assertOutput(context, extractorOutput, dumpFilesPrefix + UNKNOWN_LENGTH_EXTENSION);
} else {
DumpFileAsserts.assertOutput(context, extractorOutput, dumpFilesPrefix + ".0" + DUMP_EXTENSION);
}
SeekMap seekMap = Assertions.checkNotNull(extractorOutput.seekMap);
long durationUs = seekMap.getDurationUs();
// Only seek to the timeUs=0 if the SeekMap is unseekable or the duration is unknown.
int numberSeekTests = seekMap.isSeekable() && durationUs != C.TIME_UNSET ? 4 : 1;
for (int j = 0; j < numberSeekTests; j++) {
long timeUs = durationUs * j / 3;
long position = seekMap.getSeekPoints(timeUs).first.position;
if (timeUs == 0 && position == 0) {
// Already tested.
continue;
}
input.reset();
input.setPosition((int) position);
extractorOutput.clearTrackOutputs();
consumeTestData(extractor, input, timeUs, extractorOutput, false);
if (simulateUnknownLength && timeUs == 0) {
DumpFileAsserts.assertOutput(context, extractorOutput, dumpFilesPrefix + UNKNOWN_LENGTH_EXTENSION);
} else {
DumpFileAsserts.assertOutput(context, extractorOutput, dumpFilesPrefix + '.' + j + DUMP_EXTENSION);
}
}
}
use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.
the class FakeRenderer method render.
@Override
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
if (isEnded) {
return;
}
playbackPositionUs = positionUs;
while (true) {
if (!hasPendingBuffer) {
FormatHolder formatHolder = getFormatHolder();
buffer.clear();
@ReadDataResult int result = readSource(formatHolder, buffer, /* readFlags= */
0);
if (result == C.RESULT_FORMAT_READ) {
DrmSession.replaceSession(currentDrmSession, formatHolder.drmSession);
currentDrmSession = formatHolder.drmSession;
Format format = Assertions.checkNotNull(formatHolder.format);
if (MimeTypes.getTrackType(format.sampleMimeType) != getTrackType()) {
throw ExoPlaybackException.createForRenderer(new IllegalStateException(Util.formatInvariant("Format track type (%s) doesn't match renderer track type (%s).", MimeTypes.getTrackType(format.sampleMimeType), getTrackType())), getName(), getIndex(), format, C.FORMAT_UNSUPPORTED_TYPE, /* isRecoverable= */
false, PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
}
formatsRead.add(format);
onFormatChanged(format);
} else if (result == C.RESULT_BUFFER_READ) {
if (buffer.isEndOfStream()) {
isEnded = true;
return;
}
hasPendingBuffer = true;
} else {
Assertions.checkState(result == C.RESULT_NOTHING_READ);
return;
}
}
if (hasPendingBuffer) {
if (!shouldProcessBuffer(buffer.timeUs, positionUs)) {
return;
}
lastSamplePositionUs = buffer.timeUs;
sampleBufferReadCount++;
hasPendingBuffer = false;
}
}
}
use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.
the class FakeVideoRenderer method shouldProcessBuffer.
@Override
protected boolean shouldProcessBuffer(long bufferTimeUs, long playbackPositionUs) {
boolean shouldProcess = super.shouldProcessBuffer(bufferTimeUs, playbackPositionUs);
boolean shouldRenderFirstFrame = output != null && (!renderedFirstFrameAfterEnable ? (getState() == Renderer.STATE_STARTED || mayRenderFirstFrameAfterEnableIfNotStarted) : !renderedFirstFrameAfterReset);
shouldProcess |= shouldRenderFirstFrame && playbackPositionUs >= streamOffsetUs;
@Nullable Object output = this.output;
if (shouldProcess && !renderedFirstFrameAfterReset && output != null) {
@MonotonicNonNull Format format = Assertions.checkNotNull(this.format);
eventDispatcher.videoSizeChanged(new VideoSize(format.width, format.height, format.rotationDegrees, format.pixelWidthHeightRatio));
eventDispatcher.renderedFirstFrame(output);
renderedFirstFrameAfterReset = true;
renderedFirstFrameAfterEnable = true;
}
return shouldProcess;
}
use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.
the class DefaultPlaybackSessionManager method updateSessions.
@Override
public synchronized void updateSessions(EventTime eventTime) {
Assertions.checkNotNull(listener);
if (eventTime.timeline.isEmpty()) {
// Don't try to create new sessions for empty timelines.
return;
}
@Nullable SessionDescriptor currentSession = sessions.get(currentSessionId);
if (eventTime.mediaPeriodId != null && currentSession != null) {
// If we receive an event associated with a media period, then it needs to be either part of
// the current window if it's the first created media period, or a window that will be played
// in the future. Otherwise, we know that it belongs to a session that was already finished
// and we can ignore the event.
boolean isAlreadyFinished = currentSession.windowSequenceNumber == C.INDEX_UNSET ? currentSession.windowIndex != eventTime.windowIndex : eventTime.mediaPeriodId.windowSequenceNumber < currentSession.windowSequenceNumber;
if (isAlreadyFinished) {
return;
}
}
SessionDescriptor eventSession = getOrAddSession(eventTime.windowIndex, eventTime.mediaPeriodId);
if (currentSessionId == null) {
currentSessionId = eventSession.sessionId;
}
if (eventTime.mediaPeriodId != null && eventTime.mediaPeriodId.isAd()) {
// Ensure that the content session for an ad session is created first.
MediaPeriodId contentMediaPeriodId = new MediaPeriodId(eventTime.mediaPeriodId.periodUid, eventTime.mediaPeriodId.windowSequenceNumber, eventTime.mediaPeriodId.adGroupIndex);
SessionDescriptor contentSession = getOrAddSession(eventTime.windowIndex, contentMediaPeriodId);
if (!contentSession.isCreated) {
contentSession.isCreated = true;
eventTime.timeline.getPeriodByUid(eventTime.mediaPeriodId.periodUid, period);
long adGroupPositionMs = Util.usToMs(period.getAdGroupTimeUs(eventTime.mediaPeriodId.adGroupIndex)) + period.getPositionInWindowMs();
// getAdGroupTimeUs may return 0 for prerolls despite period offset.
adGroupPositionMs = max(0, adGroupPositionMs);
EventTime eventTimeForContent = new EventTime(eventTime.realtimeMs, eventTime.timeline, eventTime.windowIndex, contentMediaPeriodId, /* eventPlaybackPositionMs= */
adGroupPositionMs, eventTime.currentTimeline, eventTime.currentWindowIndex, eventTime.currentMediaPeriodId, eventTime.currentPlaybackPositionMs, eventTime.totalBufferedDurationMs);
listener.onSessionCreated(eventTimeForContent, contentSession.sessionId);
}
}
if (!eventSession.isCreated) {
eventSession.isCreated = true;
listener.onSessionCreated(eventTime, eventSession.sessionId);
}
if (eventSession.sessionId.equals(currentSessionId) && !eventSession.isActive) {
eventSession.isActive = true;
listener.onSessionActive(eventTime, eventSession.sessionId);
}
}
use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.
the class HlsMediaPeriod method selectTracks.
@Override
public long selectTracks(@NullableType ExoTrackSelection[] selections, boolean[] mayRetainStreamFlags, @NullableType SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
// Map each selection and stream onto a child period index.
int[] streamChildIndices = new int[selections.length];
int[] selectionChildIndices = new int[selections.length];
for (int i = 0; i < selections.length; i++) {
streamChildIndices[i] = streams[i] == null ? C.INDEX_UNSET : streamWrapperIndices.get(streams[i]);
selectionChildIndices[i] = C.INDEX_UNSET;
if (selections[i] != null) {
TrackGroup trackGroup = selections[i].getTrackGroup();
for (int j = 0; j < sampleStreamWrappers.length; j++) {
if (sampleStreamWrappers[j].getTrackGroups().indexOf(trackGroup) != C.INDEX_UNSET) {
selectionChildIndices[i] = j;
break;
}
}
}
}
boolean forceReset = false;
streamWrapperIndices.clear();
// Select tracks for each child, copying the resulting streams back into a new streams array.
SampleStream[] newStreams = new SampleStream[selections.length];
@NullableType SampleStream[] childStreams = new SampleStream[selections.length];
@NullableType ExoTrackSelection[] childSelections = new ExoTrackSelection[selections.length];
int newEnabledSampleStreamWrapperCount = 0;
HlsSampleStreamWrapper[] newEnabledSampleStreamWrappers = new HlsSampleStreamWrapper[sampleStreamWrappers.length];
for (int i = 0; i < sampleStreamWrappers.length; i++) {
for (int j = 0; j < selections.length; j++) {
childStreams[j] = streamChildIndices[j] == i ? streams[j] : null;
childSelections[j] = selectionChildIndices[j] == i ? selections[j] : null;
}
HlsSampleStreamWrapper sampleStreamWrapper = sampleStreamWrappers[i];
boolean wasReset = sampleStreamWrapper.selectTracks(childSelections, mayRetainStreamFlags, childStreams, streamResetFlags, positionUs, forceReset);
boolean wrapperEnabled = false;
for (int j = 0; j < selections.length; j++) {
SampleStream childStream = childStreams[j];
if (selectionChildIndices[j] == i) {
// Assert that the child provided a stream for the selection.
Assertions.checkNotNull(childStream);
newStreams[j] = childStream;
wrapperEnabled = true;
streamWrapperIndices.put(childStream, i);
} else if (streamChildIndices[j] == i) {
// Assert that the child cleared any previous stream.
Assertions.checkState(childStream == null);
}
}
if (wrapperEnabled) {
newEnabledSampleStreamWrappers[newEnabledSampleStreamWrapperCount] = sampleStreamWrapper;
if (newEnabledSampleStreamWrapperCount++ == 0) {
// The first enabled wrapper is always allowed to initialize timestamp adjusters. Note
// that the first wrapper will correspond to a variant, or else an audio rendition, or
// else a text rendition, in that order.
sampleStreamWrapper.setIsTimestampMaster(true);
if (wasReset || enabledSampleStreamWrappers.length == 0 || sampleStreamWrapper != enabledSampleStreamWrappers[0]) {
// The wrapper responsible for initializing the timestamp adjusters was reset or
// changed. We need to reset the timestamp adjuster provider and all other wrappers.
timestampAdjusterProvider.reset();
forceReset = true;
}
} else {
// Additional wrappers are also allowed to initialize timestamp adjusters if they contain
// audio or video, since they are expected to contain dense samples. Text wrappers are not
// permitted except in the case above in which no variant or audio rendition wrappers are
// enabled.
sampleStreamWrapper.setIsTimestampMaster(i < audioVideoSampleStreamWrapperCount);
}
}
}
// Copy the new streams back into the streams array.
System.arraycopy(newStreams, 0, streams, 0, newStreams.length);
// Update the local state.
enabledSampleStreamWrappers = Util.nullSafeArrayCopy(newEnabledSampleStreamWrappers, newEnabledSampleStreamWrapperCount);
compositeSequenceableLoader = compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(enabledSampleStreamWrappers);
return positionUs;
}
Aggregations