diff --git a/core/build.gradle b/core/build.gradle index 9967e99ff..f76ec01c9 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -63,6 +63,7 @@ dependencies { implementation "com.squareup.okio:okio:$okioVersion" implementation "de.greenrobot:eventbus:$eventbusVersion" implementation "io.reactivex:rxandroid:$rxAndroidVersion" + implementation 'com.google.android.exoplayer:exoplayer:2.7.3' implementation "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion" diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayer.java new file mode 100644 index 000000000..30c9c9ab5 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayer.java @@ -0,0 +1,252 @@ +package de.danoeh.antennapod.core.service.playback; + +import android.content.Context; +import android.net.Uri; +import android.view.SurfaceHolder; +import com.google.android.exoplayer2.DefaultLoadControl; +import com.google.android.exoplayer2.ExoPlayerFactory; +import com.google.android.exoplayer2.PlaybackParameters; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SeekParameters; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; +import com.google.android.exoplayer2.extractor.ExtractorsFactory; +import com.google.android.exoplayer2.source.ExtractorMediaSource; +import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; +import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; +import com.google.android.exoplayer2.util.Util; +import de.danoeh.antennapod.core.util.playback.IPlayer; +import org.antennapod.audio.MediaPlayer; + +import java.io.File; +import java.io.IOException; + +/** + * @author Hans-Peter Lehmann + * @version 1.0 + */ +public class ExoPlayer implements IPlayer { + private final Context mContext; + private SimpleExoPlayer mExoPlayer; + private MediaSource mediaSource; + private MediaPlayer.OnSeekCompleteListener audioSeekCompleteListener; + + public ExoPlayer(Context context) { + mContext = context; + mExoPlayer = createPlayer(); + } + + private SimpleExoPlayer createPlayer() { + SimpleExoPlayer p = ExoPlayerFactory.newSimpleInstance( + mContext, new DefaultTrackSelector(), new DefaultLoadControl()); + p.setSeekParameters(SeekParameters.PREVIOUS_SYNC); + return p; + } + + @Override + public boolean canSetPitch() { + return true; + } + + @Override + public boolean canSetSpeed() { + return true; + } + + @Override + public boolean canDownmix() { + return false; + } + + @Override + public float getCurrentPitchStepsAdjustment() { + return 0; + } + + @Override + public int getCurrentPosition() { + return (int) mExoPlayer.getCurrentPosition(); + } + + @Override + public float getCurrentSpeedMultiplier() { + return 0; + } + + @Override + public int getDuration() { + return (int) mExoPlayer.getDuration(); + } + + @Override + public float getMaxSpeedMultiplier() { + return 0; + } + + @Override + public float getMinSpeedMultiplier() { + return 0; + } + + @Override + public boolean isLooping() { + return mExoPlayer.getRepeatMode() == Player.REPEAT_MODE_ONE; + } + + @Override + public boolean isPlaying() { + return mExoPlayer.getPlayWhenReady(); + } + + @Override + public void pause() { + mExoPlayer.setPlayWhenReady(false); + } + + @Override + public void prepare() throws IllegalStateException { + mExoPlayer.prepare(mediaSource); + } + + @Override + public void prepareAsync() { + mExoPlayer.prepare(mediaSource); + } + + @Override + public void release() { + if (mExoPlayer != null) { + mExoPlayer.release(); + } + } + + @Override + public void reset() { + mExoPlayer.release(); + mExoPlayer = createPlayer(); + } + + @Override + public void seekTo(int i) throws IllegalStateException { + mExoPlayer.seekTo(i); + audioSeekCompleteListener.onSeekComplete(null); + } + + @Override + public void setAudioStreamType(int i) { + mExoPlayer.setAudioStreamType(i); + } + + @Override + public void setScreenOnWhilePlaying(boolean screenOn) { + + } + + @Override + public void setDataSource(String s) throws IllegalArgumentException, IllegalStateException, IOException { + DataSource.Factory dataSourceFactory = + new DefaultDataSourceFactory( + mContext, Util.getUserAgent(mContext, "uamp"), null); + // Produces Extractor instances for parsing the media data. + ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory(); + mediaSource = new ExtractorMediaSource( + Uri.fromFile(new File(s)), dataSourceFactory, extractorsFactory, null, null); + } + + @Override + public void setDisplay(SurfaceHolder sh) { + mExoPlayer.setVideoSurfaceHolder(sh); + } + + @Override + public void setEnableSpeedAdjustment(boolean b) { + + } + + @Override + public void setLooping(boolean b) { + mExoPlayer.setRepeatMode(b ? Player.REPEAT_MODE_ONE : Player.REPEAT_MODE_OFF); + } + + @Override + public void setPitchStepsAdjustment(float v) { + + } + + @Override + public void setPlaybackPitch(float v) { + PlaybackParameters params = mExoPlayer.getPlaybackParameters(); + mExoPlayer.setPlaybackParameters(new PlaybackParameters(params.speed, v)); + } + + @Override + public void setPlaybackSpeed(float v) { + PlaybackParameters params = mExoPlayer.getPlaybackParameters(); + mExoPlayer.setPlaybackParameters(new PlaybackParameters(v, params.pitch)); + } + + @Override + public void setDownmix(boolean b) { + + } + + @Override + public void setVolume(float v, float v1) { + mExoPlayer.setVolume(v); + } + + @Override + public void setWakeMode(Context context, int i) { + + } + + @Override + public void start() { + mExoPlayer.setPlayWhenReady(true); + } + + @Override + public void stop() { + mExoPlayer.stop(); + } + + @Override + public void setVideoScalingMode(int mode) { + mExoPlayer.setVideoScalingMode(mode); + } + + public void setOnCompletionListener(MediaPlayer.OnCompletionListener audioCompletionListener) { + } + + public void setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener audioSeekCompleteListener) { + this.audioSeekCompleteListener = audioSeekCompleteListener; + } + + public void setOnErrorListener(MediaPlayer.OnErrorListener audioErrorListener) { + } + + public void setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener audioBufferingUpdateListener) { + } + + public void setOnInfoListener(MediaPlayer.OnInfoListener audioInfoListener) { + } + + public void setOnSpeedAdjustmentAvailableChangedListener(MediaPlayer.OnSpeedAdjustmentAvailableChangedListener audioSetSpeedAbilityListener) { + } + + public int getVideoWidth() { + if (mExoPlayer.getVideoFormat() == null) { + return 0; + } + return mExoPlayer.getVideoFormat().width; + } + + public int getVideoHeight() { + if (mExoPlayer.getVideoFormat() == null) { + return 0; + } + return mExoPlayer.getVideoFormat().height; + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index af735aefd..0218bde14 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -314,7 +314,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { Log.d(TAG, "Resource prepared"); if (mediaType == MediaType.VIDEO) { - VideoPlayer vp = (VideoPlayer) mediaPlayer; + ExoPlayer vp = (ExoPlayer) mediaPlayer; videoSize = new Pair<>(vp.getVideoWidth(), vp.getVideoHeight()); } @@ -667,7 +667,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { if (mediaPlayer == null || playerStatus == PlayerStatus.ERROR || mediaType != MediaType.VIDEO) { res = null; } else { - VideoPlayer vp = (VideoPlayer) mediaPlayer; + ExoPlayer vp = (ExoPlayer) mediaPlayer; videoSize = new Pair<>(vp.getVideoWidth(), vp.getVideoHeight()); res = videoSize; } @@ -699,11 +699,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { mediaPlayer = null; return; } - if (media.getMediaType() == MediaType.VIDEO) { - mediaPlayer = new VideoPlayer(); - } else { - mediaPlayer = new AudioPlayer(context); - } + mediaPlayer = new ExoPlayer(context); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK); setMediaPlayerListeners(mediaPlayer); @@ -880,6 +876,14 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { ap.setOnBufferingUpdateListener(audioBufferingUpdateListener); ap.setOnInfoListener(audioInfoListener); ap.setOnSpeedAdjustmentAvailableChangedListener(audioSetSpeedAbilityListener); + } else if (mp instanceof ExoPlayer) { + ExoPlayer ap = (ExoPlayer) mp; + ap.setOnCompletionListener(audioCompletionListener); + ap.setOnSeekCompleteListener(audioSeekCompleteListener); + ap.setOnErrorListener(audioErrorListener); + ap.setOnBufferingUpdateListener(audioBufferingUpdateListener); + ap.setOnInfoListener(audioInfoListener); + ap.setOnSpeedAdjustmentAvailableChangedListener(audioSetSpeedAbilityListener); } else { Log.w(TAG, "Unknown media player: " + mp); }