use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.
the class ExoPlayerTest method testPlayEmptyTimeline.
/**
* Tests playback of a source that exposes an empty timeline. Playback is expected to end without
* error.
*/
public void testPlayEmptyTimeline() throws Exception {
PlayerWrapper playerWrapper = new PlayerWrapper();
Timeline timeline = Timeline.EMPTY;
MediaSource mediaSource = new FakeMediaSource(timeline, null);
FakeRenderer renderer = new FakeRenderer(null);
playerWrapper.setup(mediaSource, renderer);
playerWrapper.blockUntilEnded(TIMEOUT_MS);
assertEquals(0, playerWrapper.positionDiscontinuityCount);
assertEquals(0, renderer.formatReadCount);
assertEquals(0, renderer.bufferReadCount);
assertFalse(renderer.isEnded);
assertEquals(timeline, playerWrapper.timeline);
assertNull(playerWrapper.manifest);
}
use of com.google.android.exoplayer2.Renderer 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.Renderer in project ExoPlayer by google.
the class ExoPlayerImpl method setVideoOutputInternal.
private void setVideoOutputInternal(@Nullable Object videoOutput) {
// Note: We don't turn this method into a no-op if the output is being replaced with itself so
// as to ensure onRenderedFirstFrame callbacks are still called in this case.
List<PlayerMessage> messages = new ArrayList<>();
for (Renderer renderer : renderers) {
if (renderer.getTrackType() == TRACK_TYPE_VIDEO) {
messages.add(createMessageInternal(renderer).setType(MSG_SET_VIDEO_OUTPUT).setPayload(videoOutput).send());
}
}
boolean messageDeliveryTimedOut = false;
if (this.videoOutput != null && this.videoOutput != videoOutput) {
// renderers after this method returns.
try {
for (PlayerMessage message : messages) {
message.blockUntilDelivered(detachSurfaceTimeoutMs);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (TimeoutException e) {
messageDeliveryTimedOut = true;
}
if (this.videoOutput == ownedSurface) {
// We're replacing a surface that we are responsible for releasing.
ownedSurface.release();
ownedSurface = null;
}
}
this.videoOutput = videoOutput;
if (messageDeliveryTimedOut) {
stopInternal(/* reset= */
false, ExoPlaybackException.createForUnexpected(new ExoTimeoutException(ExoTimeoutException.TIMEOUT_OPERATION_DETACH_SURFACE), PlaybackException.ERROR_CODE_TIMEOUT));
}
}
use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.
the class ExoPlayerImplInternal method seekToPeriodPosition.
private long seekToPeriodPosition(MediaPeriodId periodId, long periodPositionUs, boolean forceDisableRenderers, boolean forceBufferingState) throws ExoPlaybackException {
stopRenderers();
isRebuffering = false;
if (forceBufferingState || playbackInfo.playbackState == Player.STATE_READY) {
setState(Player.STATE_BUFFERING);
}
// Find the requested period if it already exists.
@Nullable MediaPeriodHolder oldPlayingPeriodHolder = queue.getPlayingPeriod();
@Nullable MediaPeriodHolder newPlayingPeriodHolder = oldPlayingPeriodHolder;
while (newPlayingPeriodHolder != null) {
if (periodId.equals(newPlayingPeriodHolder.info.id)) {
break;
}
newPlayingPeriodHolder = newPlayingPeriodHolder.getNext();
}
// renderer timestamps, or if forced.
if (forceDisableRenderers || oldPlayingPeriodHolder != newPlayingPeriodHolder || (newPlayingPeriodHolder != null && newPlayingPeriodHolder.toRendererTime(periodPositionUs) < 0)) {
for (Renderer renderer : renderers) {
disableRenderer(renderer);
}
if (newPlayingPeriodHolder != null) {
// Update the queue and reenable renderers if the requested media period already exists.
while (queue.getPlayingPeriod() != newPlayingPeriodHolder) {
queue.advancePlayingPeriod();
}
queue.removeAfter(newPlayingPeriodHolder);
newPlayingPeriodHolder.setRendererOffset(MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US);
enableRenderers();
}
}
// Do the actual seeking.
if (newPlayingPeriodHolder != null) {
queue.removeAfter(newPlayingPeriodHolder);
if (!newPlayingPeriodHolder.prepared) {
newPlayingPeriodHolder.info = newPlayingPeriodHolder.info.copyWithStartPositionUs(periodPositionUs);
} else if (newPlayingPeriodHolder.hasEnabledTracks) {
periodPositionUs = newPlayingPeriodHolder.mediaPeriod.seekToUs(periodPositionUs);
newPlayingPeriodHolder.mediaPeriod.discardBuffer(periodPositionUs - backBufferDurationUs, retainBackBufferFromKeyframe);
}
resetRendererPosition(periodPositionUs);
maybeContinueLoading();
} else {
// New period has not been prepared.
queue.clear();
resetRendererPosition(periodPositionUs);
}
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */
false);
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
return periodPositionUs;
}
use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.
the class ExoPlayerImplInternal method startRenderers.
private void startRenderers() throws ExoPlaybackException {
isRebuffering = false;
mediaClock.start();
for (Renderer renderer : renderers) {
if (isRendererEnabled(renderer)) {
renderer.start();
}
}
}
Aggregations