void initialise() { heart.bind(new Heart.Heartbeat(listenersHolder.getHeartbeatCallbacks(), this)); forwarder.bind(listenersHolder.getPreparedListeners(), this); forwarder.bind(listenersHolder.getCompletionListeners(), listenersHolder.getStateChangedListeners()); forwarder.bind(listenersHolder.getErrorListeners()); forwarder.bind(listenersHolder.getBufferStateListeners()); forwarder.bind(listenersHolder.getVideoSizeChangedListeners()); forwarder.bind(listenersHolder.getBitrateChangedListeners()); forwarder.bind(listenersHolder.getInfoListeners()); forwarder.bind(listenersHolder.getDroppedVideoFramesListeners()); listenersHolder.addPreparedListener(new PreparedListener() { @Override public void onPrepared(PlayerState playerState) { loadTimeout.cancel(); } }); listenersHolder.addErrorListener(new ErrorListener() { @Override public void onError(PlayerError error) { reset(); } }); listenersHolder.addVideoSizeChangedListener(new VideoSizeChangedListener() { @Override public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { videoWidth = width; videoHeight = height; } }); }
void initialise() { forwarder.bind(listenersHolder.getPreparedListeners(), this); forwarder.bind(listenersHolder.getBufferStateListeners(), listenersHolder.getErrorListeners()); forwarder.bind(listenersHolder.getCompletionListeners(), listenersHolder.getStateChangedListeners()); forwarder.bind(listenersHolder.getVideoSizeChangedListeners()); forwarder.bind(listenersHolder.getInfoListeners()); bufferHeartbeatCallback.bind(forwarder.onHeartbeatListener()); heart.bind(new Heart.Heartbeat(listenersHolder.getHeartbeatCallbacks(), this)); listenersHolder.addHeartbeatCallback(bufferHeartbeatCallback); listenersHolder.addPreparedListener(new PreparedListener() { @Override public void onPrepared(PlayerState playerState) { loadTimeout.cancel(); mediaPlayer.setOnSeekCompleteListener(seekToResettingSeekListener); } }); listenersHolder.addErrorListener(new ErrorListener() { @Override public void onError(PlayerError error) { reset(); } }); listenersHolder.addVideoSizeChangedListener(new VideoSizeChangedListener() { @Override public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { videoWidth = width; videoHeight = height; } }); }
@Override public void attach(PlayerView playerView) { this.playerView = playerView; listenersHolder.addStateChangedListener(playerView.getStateChangedListener()); listenersHolder.addVideoSizeChangedListener(playerView.getVideoSizeChangedListener()); }
@Before public void setUp() { given(playerView.getPlayerSurfaceHolder()).willReturn(playerSurfaceHolder); given(playerView.getStateChangedListener()).willReturn(stateChangeListener); given(playerView.getVideoSizeChangedListener()).willReturn(videoSizeChangedListener); given(playerView.getContainerView()).willReturn(containerView); given(listenersHolder.getErrorListeners()).willReturn(errorListener); given(listenersHolder.getPreparedListeners()).willReturn(preparedListener); given(listenersHolder.getBufferStateListeners()).willReturn(bufferStateListener); given(listenersHolder.getCompletionListeners()).willReturn(completionListener); given(listenersHolder.getStateChangedListeners()).willReturn(stateChangedListener); given(listenersHolder.getInfoListeners()).willReturn(infoListener); given(listenersHolder.getVideoSizeChangedListeners()).willReturn(videoSizeChangedListener); given(listenersHolder.getBitrateChangedListeners()).willReturn(bitrateChangedListener); player = new ExoPlayerTwoImpl( exoPlayerFacade, listenersHolder, forwarder, loadTimeout, heart, drmSessionCreator, mediaCodecSelector ); } }
@Test public void whenReleasing_thenPlayerResourcesAreReleased() { player.release(); verify(listenersHolder).resetState(); verify(stateChangedListener).onVideoStopped(); verify(loadTimeout).cancel(); verify(heart).stopBeatingHeart(); verify(exoPlayerFacade).release(); verify(listenersHolder).clear(); }
@Test public void givenPlayerIsInitialised_whenVideoHasError_thenPlayerResourcesAreReleased_andNotListeners() { player.initialise(); ArgumentCaptor<NoPlayer.ErrorListener> argumentCaptor = ArgumentCaptor.forClass(NoPlayer.ErrorListener.class); verify(listenersHolder).addErrorListener(argumentCaptor.capture()); NoPlayer.ErrorListener errorListener = argumentCaptor.getValue(); errorListener.onError(mock(NoPlayer.PlayerError.class)); verify(listenersHolder).resetState(); verify(loadTimeout).cancel(); verify(heart).stopBeatingHeart(); verify(exoPlayerFacade).release(); verify(listenersHolder, never()).clear(); verify(stateChangedListener, never()).onVideoStopped(); }
@Test public void whenAttachingPlayerView_thenAddsVideoSizeChangedListener() { player.attach(playerView); verify(listenersHolder).addVideoSizeChangedListener(videoSizeChangedListener); }
@Override public void release() { stop(); listenersHolder.clear(); }
@Test public void whenAttachingPlayerView_thenAddsStateChangedListener() { player.attach(playerView); verify(listenersHolder).addStateChangedListener(stateChangeListener); }
@Test public void givenInitialised_whenCallingOnPrepared_thenSetsOnSeekCompleteListener() { player.initialise(); ArgumentCaptor<NoPlayer.PreparedListener> preparedListenerCaptor = ArgumentCaptor.forClass(NoPlayer.PreparedListener.class); verify(listenersHolder).addPreparedListener(preparedListenerCaptor.capture()); NoPlayer.PreparedListener preparedListener = preparedListenerCaptor.getValue(); preparedListener.onPrepared(player); verify(mediaPlayer).setOnSeekCompleteListener(any(MediaPlayer.OnSeekCompleteListener.class)); }
/** * Workaround to fix some devices (nexus 7 2013 in particular) from natively crashing the mediaplayer * by starting the mediaplayer before seeking it. */ private void initialSeekWorkaround(Either<Surface, SurfaceHolder> surface, final long initialPlayPositionInMillis) throws IllegalStateException { listenersHolder.getBufferStateListeners().onBufferStarted(); initialisePlaybackForSeeking(surface); delayedActionExecutor.performAfterDelay(new DelayedActionExecutor.Action() { @Override public void perform() { seekWithIntentToPlay(initialPlayPositionInMillis); } }, INITIAL_PLAY_SEEK_DELAY_IN_MILLIS); }
@Test public void whenInitialising_thenBindsHeartbeatCallbackToListenerHolder() { player.initialise(); verify(listenersHolder).addHeartbeatCallback(checkBufferHeartbeatCallback); }
@Test public void givenInitialised_whenCallingOnError_thenCancelsTimeout() { player.initialise(); ArgumentCaptor<NoPlayer.ErrorListener> errorListenerCaptor = ArgumentCaptor.forClass(NoPlayer.ErrorListener.class); verify(listenersHolder).addErrorListener(errorListenerCaptor.capture()); NoPlayer.ErrorListener errorListener = errorListenerCaptor.getValue(); errorListener.onError(mock(NoPlayer.PlayerError.class)); verify(loadTimeout).cancel(); }
given(listenersHolder.getPreparedListeners()).willReturn(preparedListener); given(listenersHolder.getBufferStateListeners()).willReturn(bufferStateListener); given(listenersHolder.getErrorListeners()).willReturn(errorListener); given(listenersHolder.getCompletionListeners()).willReturn(completionListener); given(listenersHolder.getVideoSizeChangedListeners()).willReturn(videoSizeChangedListener); given(listenersHolder.getInfoListeners()).willReturn(infoListener); given(listenersHolder.getStateChangedListeners()).willReturn(stateChangedListener);
@Test public void givenAttachedPlayerView_whenReleasing_thenPlayerResourcesAreReleased() { player.attach(playerView); player.release(); verify(listenersHolder).resetState(); verify(stateChangedListener).onVideoStopped(); verify(loadTimeout).cancel(); verify(heart).stopBeatingHeart(); verify(containerView).setVisibility(View.GONE); verify(exoPlayerFacade).release(); verify(listenersHolder).clear(); }
@Test public void givenInitialised_whenCallingOnError_thenPlayerResourcesAreReleased_andNotListeners() { player.initialise(); ArgumentCaptor<NoPlayer.ErrorListener> errorListenerCaptor = ArgumentCaptor.forClass(NoPlayer.ErrorListener.class); verify(listenersHolder).addErrorListener(errorListenerCaptor.capture()); NoPlayer.ErrorListener errorListener = errorListenerCaptor.getValue(); errorListener.onError(mock(NoPlayer.PlayerError.class)); verify(delayedActionExecutor).clearAllActions(); verify(listenersHolder).resetState(); verify(loadTimeout).cancel(); verify(heart).stopBeatingHeart(); verify(mediaPlayer).release(); verify(listenersHolder, never()).clear(); verify(stateChangedListener, never()).onVideoStopped(); }
@Test public void givenPlayerIsInitialised_whenAttachingPlayerView_thenAddsPlayerViewVideoSizeChangedListenerToListenersHolder() { player.initialise(); player.attach(playerView); ArgumentCaptor<NoPlayer.VideoSizeChangedListener> argumentCaptor = ArgumentCaptor.forClass(NoPlayer.VideoSizeChangedListener.class); verify(listenersHolder, times(2)).addVideoSizeChangedListener(argumentCaptor.capture()); NoPlayer.VideoSizeChangedListener videoSizeChangedListener = argumentCaptor.getAllValues().get(1); assertThat(videoSizeChangedListener).isSameAs(playerView.getVideoSizeChangedListener()); }
@Override public void release() { stop(); listenersHolder.clear(); }
@Test public void whenLoadingVideo_thenAddsStateChangedListenerToListenersHolder() { player.loadVideo(uri, OPTIONS); verify(listenersHolder).addStateChangedListener(playerView.getStateChangedListener()); }
@Test public void givenPlayerIsInitialised_whenVideoIsPrepared_thenCancelsTimeout() { player.initialise(); ArgumentCaptor<NoPlayer.PreparedListener> argumentCaptor = ArgumentCaptor.forClass(NoPlayer.PreparedListener.class); verify(listenersHolder).addPreparedListener(argumentCaptor.capture()); NoPlayer.PreparedListener preparedListener = argumentCaptor.getValue(); preparedListener.onPrepared(player); verify(loadTimeout).cancel(); }