Skip to content
This repository has been archived by the owner on Feb 11, 2022. It is now read-only.

Commit

Permalink
Merge pull request #162 from novoda/media_player_surface_holder
Browse files Browse the repository at this point in the history
Provide both Surface and SurfaceHolder in MediaPlayer
  • Loading branch information
Ryan Feline authored Jun 13, 2018
2 parents 96c267c + 1b4c87e commit 4780a8d
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static PlayerSurfaceHolder create(SurfaceView surfaceView) {
public static PlayerSurfaceHolder create(TextureView textureView) {
PlayerViewSurfaceHolder surfaceHolder = new PlayerViewSurfaceHolder();
textureView.setSurfaceTextureListener(surfaceHolder);
return new PlayerSurfaceHolder(null, textureView, new PlayerViewSurfaceHolder());
return new PlayerSurfaceHolder(null, textureView, surfaceHolder);
}

PlayerSurfaceHolder(@Nullable SurfaceView surfaceView, @Nullable TextureView textureView, PlayerViewSurfaceHolder surfaceHolder) {
Expand Down
33 changes: 17 additions & 16 deletions core/src/main/java/com/novoda/noplayer/PlayerViewSurfaceHolder.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.TextureView;
import com.novoda.noplayer.model.Either;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -13,12 +14,12 @@ class PlayerViewSurfaceHolder implements SurfaceHolder.Callback, TextureView.Sur

private final List<Callback> callbacks = new ArrayList<>();
@Nullable
private Surface surface;
private Either<Surface, SurfaceHolder> eitherSurface;

@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
this.surface = surfaceHolder.getSurface();
notifyListeners(surface);
this.eitherSurface = Either.right(surfaceHolder);
notifyListeners(eitherSurface);
callbacks.clear();
}

Expand All @@ -35,11 +36,17 @@ public void surfaceDestroyed(SurfaceHolder holder) {

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
this.surface = new Surface(surfaceTexture);
notifyListeners(surface);
this.eitherSurface = Either.left(new Surface(surfaceTexture));
notifyListeners(eitherSurface);
callbacks.clear();
}

private void notifyListeners(Either<Surface, SurfaceHolder> either) {
for (Callback callback : callbacks) {
callback.onSurfaceReady(either);
}
}

@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// do nothing
Expand All @@ -58,27 +65,21 @@ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// do nothing
}

private void notifyListeners(Surface surface) {
for (Callback callback : callbacks) {
callback.onSurfaceReady(surface);
}
}

private void setSurfaceNotReady() {
surface = null;
eitherSurface = null;
}

@Override
public void requestSurface(Callback callback) {
if (isSurfaceHolderReady()) {
callback.onSurfaceReady(surface);
if (isSurfaceReady()) {
callback.onSurfaceReady(eitherSurface);
} else {
callbacks.add(callback);
}
}

private boolean isSurfaceHolderReady() {
return surface != null;
private boolean isSurfaceReady() {
return eitherSurface != null;
}

@Override
Expand Down
5 changes: 3 additions & 2 deletions core/src/main/java/com/novoda/noplayer/SurfaceRequester.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.novoda.noplayer;

import android.view.Surface;
import android.view.SurfaceHolder;
import com.novoda.noplayer.model.Either;

public interface SurfaceRequester {

Expand All @@ -10,8 +12,7 @@ public interface SurfaceRequester {

interface Callback {

void onSurfaceReady(Surface surface);

void onSurfaceReady(Either<Surface, SurfaceHolder> surface);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
import android.net.Uri;
import android.support.annotation.Nullable;
import android.view.Surface;

import android.view.SurfaceHolder;
import com.novoda.noplayer.internal.mediaplayer.PlaybackStateChecker.PlaybackState;
import com.novoda.noplayer.internal.mediaplayer.forwarder.MediaPlayerForwarder;
import com.novoda.noplayer.internal.utils.NoPlayerLog;
import com.novoda.noplayer.internal.utils.Optional;
import com.novoda.noplayer.model.AudioTracks;
import com.novoda.noplayer.model.Either;
import com.novoda.noplayer.model.PlayerAudioTrack;
import com.novoda.noplayer.model.PlayerSubtitleTrack;
import com.novoda.noplayer.model.PlayerVideoTrack;
Expand Down Expand Up @@ -67,7 +68,7 @@ static AndroidMediaPlayerFacade newInstance(Context context, MediaPlayerForwarde
this.mediaPlayerCreator = mediaPlayerCreator;
}

void prepareVideo(Uri videoUri, Surface surface) {
void prepareVideo(Uri videoUri, Either<Surface, SurfaceHolder> surface) {
requestAudioFocus();
release();
try {
Expand All @@ -83,7 +84,7 @@ private void requestAudioFocus() {
audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
}

private MediaPlayer createAndBindMediaPlayer(Surface surface,
private MediaPlayer createAndBindMediaPlayer(Either<Surface, SurfaceHolder> surface,
Uri videoUri) throws IOException, IllegalStateException, IllegalArgumentException {
MediaPlayer mediaPlayer = mediaPlayerCreator.createMediaPlayer();
mediaPlayer.setOnPreparedListener(internalPreparedListener);
Expand All @@ -92,7 +93,7 @@ private MediaPlayer createAndBindMediaPlayer(Surface surface,
mediaPlayer.setOnErrorListener(internalErrorListener);
mediaPlayer.setOnBufferingUpdateListener(internalBufferingUpdateListener);
mediaPlayer.setDataSource(context, videoUri, NO_HEADERS);
mediaPlayer.setSurface(surface);
attachSurface(mediaPlayer, surface);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setScreenOnWhilePlaying(true);

Expand Down Expand Up @@ -173,13 +174,29 @@ void release() {
}
}

void start(Surface surface) throws IllegalStateException {
void start(Either<Surface, SurfaceHolder> surface) throws IllegalStateException {
assertIsInPlaybackState();
mediaPlayer.setSurface(surface);
attachSurface(mediaPlayer, surface);
currentState = PLAYING;
mediaPlayer.start();
}

private void attachSurface(final MediaPlayer mediaPlayer, Either<Surface, SurfaceHolder> surface) {
Either.Consumer<Surface> setSurface = new Either.Consumer<Surface>() {
@Override
public void accept(Surface value) {
mediaPlayer.setSurface(value);
}
};
Either.Consumer<SurfaceHolder> setDisplay = new Either.Consumer<SurfaceHolder>() {
@Override
public void accept(SurfaceHolder value) {
mediaPlayer.setDisplay(value);
}
};
surface.apply(setSurface, setDisplay);
}

void pause() throws IllegalStateException {
assertIsInPlaybackState();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,22 @@
import android.media.MediaPlayer;
import android.net.Uri;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
import com.novoda.noplayer.Listeners;
import com.novoda.noplayer.NoPlayer;
import com.novoda.noplayer.Options;
import com.novoda.noplayer.PlayerInformation;
import com.novoda.noplayer.PlayerState;
import com.novoda.noplayer.PlayerView;
import com.novoda.noplayer.PlayerSurfaceHolder;
import com.novoda.noplayer.PlayerView;
import com.novoda.noplayer.SurfaceRequester;
import com.novoda.noplayer.internal.Heart;
import com.novoda.noplayer.internal.listeners.PlayerListenersHolder;
import com.novoda.noplayer.internal.mediaplayer.forwarder.MediaPlayerForwarder;
import com.novoda.noplayer.internal.utils.Optional;
import com.novoda.noplayer.model.AudioTracks;
import com.novoda.noplayer.model.Either;
import com.novoda.noplayer.model.LoadTimeout;
import com.novoda.noplayer.model.PlayerAudioTrack;
import com.novoda.noplayer.model.PlayerSubtitleTrack;
Expand Down Expand Up @@ -146,7 +148,7 @@ public void play() throws IllegalStateException {
heart.startBeatingHeart();
requestSurface(new SurfaceRequester.Callback() {
@Override
public void onSurfaceReady(Surface surface) {
public void onSurfaceReady(Either<Surface, SurfaceHolder> surface) {
mediaPlayer.start(surface);
listenersHolder.getStateChangedListeners().onVideoPlaying();
}
Expand All @@ -160,7 +162,7 @@ public void playAt(final long positionInMillis) throws IllegalStateException {
} else {
requestSurface(new SurfaceRequester.Callback() {
@Override
public void onSurfaceReady(Surface surface) {
public void onSurfaceReady(Either<Surface, SurfaceHolder> surface) {
initialSeekWorkaround(surface, positionInMillis);
}
});
Expand All @@ -171,7 +173,7 @@ public void onSurfaceReady(Surface surface) {
* 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(Surface surface, final long initialPlayPositionInMillis) throws IllegalStateException {
private void initialSeekWorkaround(Either<Surface, SurfaceHolder> surface, final long initialPlayPositionInMillis) throws IllegalStateException {
listenersHolder.getBufferStateListeners().onBufferStarted();
initialisePlaybackForSeeking(surface);
delayedActionExecutor.performAfterDelay(new DelayedActionExecutor.Action() {
Expand All @@ -182,7 +184,7 @@ public void perform() {
}, INITIAL_PLAY_SEEK_DELAY_IN_MILLIS);
}

private void initialisePlaybackForSeeking(Surface surface) {
private void initialisePlaybackForSeeking(Either<Surface, SurfaceHolder> surface) {
mediaPlayer.start(surface);
mediaPlayer.pause();
}
Expand Down Expand Up @@ -231,7 +233,7 @@ public void loadVideo(final Uri uri, final Options options) {
listenersHolder.getBufferStateListeners().onBufferStarted();
requestSurface(new SurfaceRequester.Callback() {
@Override
public void onSurfaceReady(Surface surface) {
public void onSurfaceReady(Either<Surface, SurfaceHolder> surface) {
mediaPlayer.prepareVideo(uri, surface);
}
});
Expand Down
50 changes: 50 additions & 0 deletions core/src/main/java/com/novoda/noplayer/model/Either.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.novoda.noplayer.model;

public abstract class Either<L, R> {

public static <L, R> Either<L, R> left(L left) {
return new Left<>(left);
}

public static <L, R> Either<L, R> right(R right) {
return new Right<>(right);
}

Either() {
// restrict subclasses to the package
}

public abstract void apply(Consumer<L> leftConsumer, Consumer<R> rightConsumer);

static class Left<L, R> extends Either<L, R> {

private final L valueLeft;

Left(L valueLeft) {
this.valueLeft = valueLeft;
}

@Override
public void apply(Consumer<L> leftConsumer, Consumer<R> rightConsumer) {
leftConsumer.accept(valueLeft);
}
}

static class Right<L, R> extends Either<L, R> {

private final R valueRight;

Right(R valueRight) {
this.valueRight = valueRight;
}

@Override
public void apply(Consumer<L> leftConsumer, Consumer<R> rightConsumer) {
rightConsumer.accept(valueRight);
}
}

public interface Consumer<T> {
void accept(T value);
}
}
Loading

0 comments on commit 4780a8d

Please sign in to comment.