Search in sources :

Example 66 with Renderer

use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.

the class ExoPlayerTest method renderersLifecycle_seekTo_resetsDisabledRenderersIfRequired.

@Test
public void renderersLifecycle_seekTo_resetsDisabledRenderersIfRequired() throws Exception {
    Timeline timeline = new FakeTimeline();
    final FakeRenderer audioRenderer = new FakeRenderer(C.TRACK_TYPE_AUDIO);
    final FakeRenderer videoRenderer = new FakeRenderer(C.TRACK_TYPE_VIDEO);
    final FakeRenderer textRenderer = new FakeRenderer(C.TRACK_TYPE_TEXT);
    Format textFormat = new Format.Builder().setSampleMimeType(MimeTypes.TEXT_VTT).setLanguage("en").build();
    ExoPlayer player = new TestExoPlayerBuilder(context).setRenderers(videoRenderer, audioRenderer, textRenderer).build();
    Player.Listener mockPlayerListener = mock(Player.Listener.class);
    player.addListener(mockPlayerListener);
    player.setTrackSelectionParameters(player.getTrackSelectionParameters().buildUpon().setPreferredTextLanguage("en").build());
    player.setMediaSources(ImmutableList.of(new FakeMediaSource(timeline, ExoPlayerTestRunner.AUDIO_FORMAT), new FakeMediaSource(timeline, ExoPlayerTestRunner.AUDIO_FORMAT, textFormat)));
    player.prepare();
    player.play();
    runUntilPositionDiscontinuity(player, Player.DISCONTINUITY_REASON_AUTO_TRANSITION);
    // Disable text renderer by selecting a language that is not available.
    player.setTrackSelectionParameters(player.getTrackSelectionParameters().buildUpon().setPreferredTextLanguage("de").build());
    player.seekTo(/* mediaItemIndex= */
    0, /* positionMs= */
    1000);
    runUntilPlaybackState(player, Player.STATE_READY);
    // Expect formerly enabled renderers to be reset after seek.
    assertThat(textRenderer.resetCount).isEqualTo(1);
    assertThat(audioRenderer.resetCount).isEqualTo(0);
    assertThat(videoRenderer.resetCount).isEqualTo(0);
    runUntilPlaybackState(player, Player.STATE_ENDED);
    player.release();
    // Verify that the text renderer has not been reset a second time.
    assertThat(audioRenderer.enabledCount).isEqualTo(2);
    assertThat(audioRenderer.resetCount).isEqualTo(1);
    assertThat(textRenderer.enabledCount).isEqualTo(1);
    assertThat(textRenderer.resetCount).isEqualTo(1);
    assertThat(videoRenderer.enabledCount).isEqualTo(0);
    assertThat(videoRenderer.resetCount).isEqualTo(0);
}
Also used : FakeRenderer(com.google.android.exoplayer2.testutil.FakeRenderer) Listener(com.google.android.exoplayer2.Player.Listener) NoUidTimeline(com.google.android.exoplayer2.testutil.NoUidTimeline) SinglePeriodTimeline(com.google.android.exoplayer2.source.SinglePeriodTimeline) FakeTimeline(com.google.android.exoplayer2.testutil.FakeTimeline) FakeMediaSource(com.google.android.exoplayer2.testutil.FakeMediaSource) FakeTimeline(com.google.android.exoplayer2.testutil.FakeTimeline) TestExoPlayerBuilder(com.google.android.exoplayer2.testutil.TestExoPlayerBuilder) Test(org.junit.Test)

Example 67 with Renderer

use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.

the class ExoPlayerTest method playEmptyTimeline.

/**
 * Tests playback of a source that exposes an empty timeline. Playback is expected to end without
 * error.
 */
@Test
public void playEmptyTimeline() throws Exception {
    Timeline timeline = Timeline.EMPTY;
    Timeline expectedMaskingTimeline = new MaskingMediaSource.PlaceholderTimeline(FakeMediaSource.FAKE_MEDIA_ITEM);
    FakeRenderer renderer = new FakeRenderer(C.TRACK_TYPE_UNKNOWN);
    ExoPlayer player = new TestExoPlayerBuilder(context).setRenderers(renderer).build();
    Player.Listener mockListener = mock(Player.Listener.class);
    player.addListener(mockListener);
    player.setMediaSource(new FakeMediaSource(timeline, ExoPlayerTestRunner.VIDEO_FORMAT));
    player.prepare();
    player.play();
    runUntilPlaybackState(player, Player.STATE_ENDED);
    InOrder inOrder = inOrder(mockListener);
    inOrder.verify(mockListener).onTimelineChanged(argThat(noUid(expectedMaskingTimeline)), eq(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED));
    inOrder.verify(mockListener).onTimelineChanged(argThat(noUid(timeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
    inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
    inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
    assertThat(renderer.getFormatsRead()).isEmpty();
    assertThat(renderer.sampleBufferReadCount).isEqualTo(0);
    assertThat(renderer.isEnded).isFalse();
}
Also used : FakeRenderer(com.google.android.exoplayer2.testutil.FakeRenderer) Listener(com.google.android.exoplayer2.Player.Listener) NoUidTimeline(com.google.android.exoplayer2.testutil.NoUidTimeline) SinglePeriodTimeline(com.google.android.exoplayer2.source.SinglePeriodTimeline) FakeTimeline(com.google.android.exoplayer2.testutil.FakeTimeline) InOrder(org.mockito.InOrder) FakeMediaSource(com.google.android.exoplayer2.testutil.FakeMediaSource) TestExoPlayerBuilder(com.google.android.exoplayer2.testutil.TestExoPlayerBuilder) Test(org.junit.Test)

Example 68 with Renderer

use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.

the class MediaCodecAudioRendererTest method supportsFormat_withEac3JocMediaAndEac3Decoder_returnsTrue.

@Test
public void supportsFormat_withEac3JocMediaAndEac3Decoder_returnsTrue() throws Exception {
    Format mediaFormat = new Format.Builder().setSampleMimeType(MimeTypes.AUDIO_E_AC3_JOC).setCodecs(MimeTypes.CODEC_E_AC3_JOC).build();
    MediaCodecSelector mediaCodecSelector = (mimeType, requiresSecureDecoder, requiresTunnelingDecoder) -> !mimeType.equals(MimeTypes.AUDIO_E_AC3) ? ImmutableList.of() : ImmutableList.of(MediaCodecInfo.newInstance(/* name= */
    "eac3-codec", /* mimeType= */
    mimeType, /* codecMimeType= */
    mimeType, /* capabilities= */
    null, /* hardwareAccelerated= */
    false, /* softwareOnly= */
    true, /* vendor= */
    false, /* forceDisableAdaptive= */
    false, /* forceSecure= */
    false));
    MediaCodecAudioRenderer renderer = new MediaCodecAudioRenderer(ApplicationProvider.getApplicationContext(), mediaCodecSelector, /* enableDecoderFallback= */
    false, /* eventHandler= */
    new Handler(Looper.getMainLooper()), audioRendererEventListener, audioSink);
    renderer.init(/* index= */
    0, PlayerId.UNSET);
    @Capabilities int capabilities = renderer.supportsFormat(mediaFormat);
    assertThat(RendererCapabilities.getFormatSupport(capabilities)).isEqualTo(C.FORMAT_HANDLED);
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) ExoPlaybackException(com.google.android.exoplayer2.ExoPlaybackException) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) MediaFormat(android.media.MediaFormat) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities) Mock(org.mockito.Mock) Assert.assertThrows(org.junit.Assert.assertThrows) RunWith(org.junit.runner.RunWith) SystemClock(android.os.SystemClock) AndroidJUnit4(androidx.test.ext.junit.runners.AndroidJUnit4) Shadows.shadowOf(org.robolectric.Shadows.shadowOf) ApplicationProvider(androidx.test.core.app.ApplicationProvider) Format(com.google.android.exoplayer2.Format) PlayerId(com.google.android.exoplayer2.analytics.PlayerId) MediaCodecInfo(com.google.android.exoplayer2.mediacodec.MediaCodecInfo) ArgumentCaptor(org.mockito.ArgumentCaptor) DrmSessionEventListener(com.google.android.exoplayer2.drm.DrmSessionEventListener) MimeTypes(com.google.android.exoplayer2.util.MimeTypes) ImmutableList(com.google.common.collect.ImmutableList) Handler(android.os.Handler) Looper(android.os.Looper) MockitoJUnit(org.mockito.junit.MockitoJUnit) ArgumentMatchers.anyInt(org.mockito.ArgumentMatchers.anyInt) FakeSampleStream(com.google.android.exoplayer2.testutil.FakeSampleStream) DefaultAllocator(com.google.android.exoplayer2.upstream.DefaultAllocator) C(com.google.android.exoplayer2.C) Before(org.junit.Before) FakeSampleStreamItem.format(com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.format) Capabilities(com.google.android.exoplayer2.RendererCapabilities.Capabilities) END_OF_STREAM_ITEM(com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM) Mockito.atLeastOnce(org.mockito.Mockito.atLeastOnce) Test(org.junit.Test) Mockito.when(org.mockito.Mockito.when) Truth.assertThat(com.google.common.truth.Truth.assertThat) Mockito.verify(org.mockito.Mockito.verify) FakeSampleStreamItem.oneByteSample(com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample) Nullable(androidx.annotation.Nullable) Rule(org.junit.Rule) RendererConfiguration(com.google.android.exoplayer2.RendererConfiguration) MediaCodecSelector(com.google.android.exoplayer2.mediacodec.MediaCodecSelector) PlaybackException(com.google.android.exoplayer2.PlaybackException) DrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager) MockitoRule(org.mockito.junit.MockitoRule) Collections(java.util.Collections) MediaCodecSelector(com.google.android.exoplayer2.mediacodec.MediaCodecSelector) MediaFormat(android.media.MediaFormat) Format(com.google.android.exoplayer2.Format) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities) Capabilities(com.google.android.exoplayer2.RendererCapabilities.Capabilities) Handler(android.os.Handler) Test(org.junit.Test)

Example 69 with Renderer

use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.

the class ExoPlayerTest method shuffleModeEnabledChanges.

@Test
public void shuffleModeEnabledChanges() throws Exception {
    Timeline fakeTimeline = new FakeTimeline();
    MediaSource[] fakeMediaSources = { new FakeMediaSource(fakeTimeline, ExoPlayerTestRunner.VIDEO_FORMAT), new FakeMediaSource(fakeTimeline, ExoPlayerTestRunner.VIDEO_FORMAT), new FakeMediaSource(fakeTimeline, ExoPlayerTestRunner.VIDEO_FORMAT) };
    ConcatenatingMediaSource mediaSource = new ConcatenatingMediaSource(false, new FakeShuffleOrder(3), fakeMediaSources);
    FakeRenderer renderer = new FakeRenderer(C.TRACK_TYPE_VIDEO);
    ActionSchedule actionSchedule = new ActionSchedule.Builder(TAG).pause().waitForPlaybackState(Player.STATE_READY).setRepeatMode(Player.REPEAT_MODE_ALL).playUntilStartOfMediaItem(/* mediaItemIndex= */
    1).setShuffleModeEnabled(true).playUntilStartOfMediaItem(/* mediaItemIndex= */
    1).setShuffleModeEnabled(false).setRepeatMode(Player.REPEAT_MODE_OFF).play().build();
    ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder(context).setMediaSources(mediaSource).setRenderers(renderer).setActionSchedule(actionSchedule).build().start().blockUntilEnded(TIMEOUT_MS);
    testRunner.assertPlayedPeriodIndices(0, 1, 0, 2, 1, 2);
    testRunner.assertPositionDiscontinuityReasonsEqual(Player.DISCONTINUITY_REASON_AUTO_TRANSITION, Player.DISCONTINUITY_REASON_AUTO_TRANSITION, Player.DISCONTINUITY_REASON_AUTO_TRANSITION, Player.DISCONTINUITY_REASON_AUTO_TRANSITION, Player.DISCONTINUITY_REASON_AUTO_TRANSITION);
    assertThat(renderer.isEnded).isTrue();
}
Also used : FakeRenderer(com.google.android.exoplayer2.testutil.FakeRenderer) NoUidTimeline(com.google.android.exoplayer2.testutil.NoUidTimeline) SinglePeriodTimeline(com.google.android.exoplayer2.source.SinglePeriodTimeline) FakeTimeline(com.google.android.exoplayer2.testutil.FakeTimeline) ServerSideAdInsertionMediaSource(com.google.android.exoplayer2.source.ads.ServerSideAdInsertionMediaSource) FakeAdaptiveMediaSource(com.google.android.exoplayer2.testutil.FakeAdaptiveMediaSource) MaskingMediaSource(com.google.android.exoplayer2.source.MaskingMediaSource) ConcatenatingMediaSource(com.google.android.exoplayer2.source.ConcatenatingMediaSource) MediaSource(com.google.android.exoplayer2.source.MediaSource) CompositeMediaSource(com.google.android.exoplayer2.source.CompositeMediaSource) ClippingMediaSource(com.google.android.exoplayer2.source.ClippingMediaSource) FakeMediaSource(com.google.android.exoplayer2.testutil.FakeMediaSource) FakeMediaSource(com.google.android.exoplayer2.testutil.FakeMediaSource) ActionSchedule(com.google.android.exoplayer2.testutil.ActionSchedule) FakeTimeline(com.google.android.exoplayer2.testutil.FakeTimeline) TestExoPlayerBuilder(com.google.android.exoplayer2.testutil.TestExoPlayerBuilder) ConcatenatingMediaSource(com.google.android.exoplayer2.source.ConcatenatingMediaSource) ExoPlayerTestRunner(com.google.android.exoplayer2.testutil.ExoPlayerTestRunner) FakeShuffleOrder(com.google.android.exoplayer2.testutil.FakeShuffleOrder) Test(org.junit.Test)

Example 70 with Renderer

use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.

the class MediaCodecRenderer method onInputFormatChanged.

/**
 * Called when a new {@link Format} is read from the upstream {@link MediaPeriod}.
 *
 * @param formatHolder A {@link FormatHolder} that holds the new {@link Format}.
 * @throws ExoPlaybackException If an error occurs re-initializing the {@link MediaCodec}.
 * @return The result of the evaluation to determine whether the existing decoder instance can be
 *     reused for the new format, or {@code null} if the renderer did not have a decoder.
 */
@CallSuper
@Nullable
protected DecoderReuseEvaluation onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybackException {
    waitingForFirstSampleInFormat = true;
    Format newFormat = checkNotNull(formatHolder.format);
    if (newFormat.sampleMimeType == null) {
        throw createRendererException(new IllegalArgumentException(), newFormat, PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
    }
    setSourceDrmSession(formatHolder.drmSession);
    inputFormat = newFormat;
    if (bypassEnabled) {
        bypassDrainAndReinitialize = true;
        // Need to drain batch buffer first.
        return null;
    }
    if (codec == null) {
        availableCodecInfos = null;
        maybeInitCodecOrBypass();
        return null;
    }
    // We have an existing codec that we may need to reconfigure, re-initialize, or release to
    // switch to bypass. If the existing codec instance is kept then its operating rate and DRM
    // session may need to be updated.
    // Copy the current codec and codecInfo to local variables so they remain accessible if the
    // member variables are updated during the logic below.
    MediaCodecAdapter codec = this.codec;
    MediaCodecInfo codecInfo = this.codecInfo;
    Format oldFormat = codecInputFormat;
    if (drmNeedsCodecReinitialization(codecInfo, newFormat, codecDrmSession, sourceDrmSession)) {
        drainAndReinitializeCodec();
        return new DecoderReuseEvaluation(codecInfo.name, oldFormat, newFormat, REUSE_RESULT_NO, DISCARD_REASON_DRM_SESSION_CHANGED);
    }
    boolean drainAndUpdateCodecDrmSession = sourceDrmSession != codecDrmSession;
    Assertions.checkState(!drainAndUpdateCodecDrmSession || Util.SDK_INT >= 23);
    DecoderReuseEvaluation evaluation = canReuseCodec(codecInfo, oldFormat, newFormat);
    @DecoderDiscardReasons int overridingDiscardReasons = 0;
    switch(evaluation.result) {
        case REUSE_RESULT_NO:
            drainAndReinitializeCodec();
            break;
        case REUSE_RESULT_YES_WITH_FLUSH:
            if (!updateCodecOperatingRate(newFormat)) {
                overridingDiscardReasons |= DISCARD_REASON_OPERATING_RATE_CHANGED;
            } else {
                codecInputFormat = newFormat;
                if (drainAndUpdateCodecDrmSession) {
                    if (!drainAndUpdateCodecDrmSessionV23()) {
                        overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                    }
                } else if (!drainAndFlushCodec()) {
                    overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                }
            }
            break;
        case REUSE_RESULT_YES_WITH_RECONFIGURATION:
            if (!updateCodecOperatingRate(newFormat)) {
                overridingDiscardReasons |= DISCARD_REASON_OPERATING_RATE_CHANGED;
            } else {
                codecReconfigured = true;
                codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
                codecNeedsAdaptationWorkaroundBuffer = codecAdaptationWorkaroundMode == ADAPTATION_WORKAROUND_MODE_ALWAYS || (codecAdaptationWorkaroundMode == ADAPTATION_WORKAROUND_MODE_SAME_RESOLUTION && newFormat.width == oldFormat.width && newFormat.height == oldFormat.height);
                codecInputFormat = newFormat;
                if (drainAndUpdateCodecDrmSession && !drainAndUpdateCodecDrmSessionV23()) {
                    overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                }
            }
            break;
        case REUSE_RESULT_YES_WITHOUT_RECONFIGURATION:
            if (!updateCodecOperatingRate(newFormat)) {
                overridingDiscardReasons |= DISCARD_REASON_OPERATING_RATE_CHANGED;
            } else {
                codecInputFormat = newFormat;
                if (drainAndUpdateCodecDrmSession && !drainAndUpdateCodecDrmSessionV23()) {
                    overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                }
            }
            break;
        default:
            // Never happens.
            throw new IllegalStateException();
    }
    if (evaluation.result != REUSE_RESULT_NO && (this.codec != codec || codecDrainAction == DRAIN_ACTION_REINITIALIZE)) {
        // The reasons are indicated by overridingDiscardReasons.
        return new DecoderReuseEvaluation(codecInfo.name, oldFormat, newFormat, REUSE_RESULT_NO, overridingDiscardReasons);
    }
    return evaluation;
}
Also used : Format(com.google.android.exoplayer2.Format) MediaFormat(android.media.MediaFormat) DecoderReuseEvaluation(com.google.android.exoplayer2.decoder.DecoderReuseEvaluation) DecoderDiscardReasons(com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DecoderDiscardReasons) CallSuper(androidx.annotation.CallSuper) Nullable(androidx.annotation.Nullable)

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