Search in sources :

Example 46 with Renderer

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);
}
Also used : MediaSource(com.google.android.exoplayer2.source.MediaSource)

Example 47 with Renderer

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;
        }
    }
}
Also used : Format(com.google.android.exoplayer2.Format) ReadDataResult(com.google.android.exoplayer2.source.SampleStream.ReadDataResult) FormatHolder(com.google.android.exoplayer2.FormatHolder)

Example 48 with Renderer

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));
    }
}
Also used : ArrayList(java.util.ArrayList) VideoDecoderOutputBufferRenderer(com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer) TimeoutException(java.util.concurrent.TimeoutException)

Example 49 with Renderer

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;
}
Also used : TextRenderer(com.google.android.exoplayer2.text.TextRenderer) Nullable(androidx.annotation.Nullable)

Example 50 with Renderer

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();
        }
    }
}
Also used : TextRenderer(com.google.android.exoplayer2.text.TextRenderer)

Aggregations

Test (org.junit.Test)36 FakeRenderer (com.google.android.exoplayer2.testutil.FakeRenderer)27 Nullable (androidx.annotation.Nullable)25 FakeMediaSource (com.google.android.exoplayer2.testutil.FakeMediaSource)25 FakeTimeline (com.google.android.exoplayer2.testutil.FakeTimeline)25 TestExoPlayerBuilder (com.google.android.exoplayer2.testutil.TestExoPlayerBuilder)24 TextRenderer (com.google.android.exoplayer2.text.TextRenderer)21 TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)19 ArrayList (java.util.ArrayList)18 SinglePeriodTimeline (com.google.android.exoplayer2.source.SinglePeriodTimeline)17 NoUidTimeline (com.google.android.exoplayer2.testutil.NoUidTimeline)17 MediaSource (com.google.android.exoplayer2.source.MediaSource)16 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)16 ActionSchedule (com.google.android.exoplayer2.testutil.ActionSchedule)16 Format (com.google.android.exoplayer2.Format)15 Listener (com.google.android.exoplayer2.Player.Listener)15 ExoPlayerTestRunner (com.google.android.exoplayer2.testutil.ExoPlayerTestRunner)15 TimelineWindowDefinition (com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition)14 InOrder (org.mockito.InOrder)14 ConcatenatingMediaSource (com.google.android.exoplayer2.source.ConcatenatingMediaSource)13