|
@@ -0,0 +1,226 @@
|
|
|
+package com.daya.orchestra.accompany.presenter;
|
|
|
+
|
|
|
+import android.content.Context;
|
|
|
+import android.media.AudioManager;
|
|
|
+import android.net.Uri;
|
|
|
+import android.util.Log;
|
|
|
+import android.view.SurfaceHolder;
|
|
|
+
|
|
|
+import com.cooleshow.base.utils.LOG;
|
|
|
+import com.daya.orchestra.accompany.common.Constants;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+
|
|
|
+import tv.danmaku.ijk.media.player.IMediaPlayer;
|
|
|
+import tv.danmaku.ijk.media.player.IjkMediaPlayer;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Author by pq, Date on 2023/5/11.
|
|
|
+ */
|
|
|
+public class CustomIJKPlayer implements IjkMediaPlayer.OnErrorListener, IjkMediaPlayer.OnCompletionListener, IjkMediaPlayer.OnPreparedListener {
|
|
|
+ public static final String TAG = "CustomPlayer";
|
|
|
+ private Context mContext;
|
|
|
+ IjkMediaPlayer mPlayer;
|
|
|
+ private boolean hasPrepared;
|
|
|
+ private boolean isStoped = false;
|
|
|
+
|
|
|
+ private boolean isNeedMute = false;
|
|
|
+
|
|
|
+ private int prepareSeekPosition = -1;//此字段用于选段播放
|
|
|
+
|
|
|
+ public CustomIJKPlayer() {
|
|
|
+ initPlayer();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initPlayer() {
|
|
|
+ if (null == mPlayer) {
|
|
|
+ mPlayer = new IjkMediaPlayer();
|
|
|
+ mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
|
|
+ mPlayer.setOnErrorListener(this);
|
|
|
+ mPlayer.setOnCompletionListener(this);
|
|
|
+ mPlayer.setOnPreparedListener(this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setOnCompletionListener(IjkMediaPlayer.OnCompletionListener listener) {
|
|
|
+ if (mPlayer != null) {
|
|
|
+ mPlayer.setOnCompletionListener(listener);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void play(Context context, Uri dataSource) {
|
|
|
+ hasPrepared = false; // 开始播放前讲Flag置为不可操作
|
|
|
+ isStoped = false;
|
|
|
+ initPlayer(); // 如果是第一次播放/player已经释放了,就会重新创建、初始化
|
|
|
+ try {
|
|
|
+ mPlayer.reset();
|
|
|
+ mPlayer.setDataSource(context, dataSource); // 设置曲目资源
|
|
|
+ mPlayer.prepareAsync(); // 异步的准备方法
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void play(boolean isMute, float speed,String path) {
|
|
|
+ hasPrepared = false; // 开始播放前讲Flag置为不可操作
|
|
|
+ isStoped = false; //
|
|
|
+ this.isNeedMute = isMute;
|
|
|
+ initPlayer(); // 如果是第一次播放/player已经释放了,就会重新创建、初始化
|
|
|
+ try {
|
|
|
+ mPlayer.reset();
|
|
|
+ initOptions(speed);
|
|
|
+ mPlayer.setDataSource(path); // 设置曲目资源
|
|
|
+ mPlayer.prepareAsync(); // 异步的准备方法
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initOptions(float speed) {
|
|
|
+ if(speed != Constants.DEFAULT_PLAY_SPEED){
|
|
|
+ mPlayer.setSpeed(speed);
|
|
|
+ mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "soundtouch", 1);
|
|
|
+ }
|
|
|
+ mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1);
|
|
|
+ // 设置缓存策略
|
|
|
+ mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 1);
|
|
|
+ mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 5);
|
|
|
+ mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", 4);
|
|
|
+ //硬件加速
|
|
|
+ mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
|
|
|
+ mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1);
|
|
|
+ // 调整同步设置
|
|
|
+ mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "sync", "audio");
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getPrepareSeekPosition() {
|
|
|
+ return prepareSeekPosition;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getExceptTargetPos(long cu) {
|
|
|
+ //用于选段评测流程 如果有选段快进则需要 按照快进开播播放的位置取
|
|
|
+ long targetPos = getPrepareSeekPosition() != -1 ? cu - getPrepareSeekPosition() : cu;
|
|
|
+ return targetPos;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setPrepareSeekPosition(int prepareSeekPosition) {
|
|
|
+ this.prepareSeekPosition = prepareSeekPosition;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getCu() {
|
|
|
+ if (mPlayer != null) {
|
|
|
+ long currentPosition = mPlayer.getCurrentPosition();
|
|
|
+ return currentPosition;
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public long getT() {
|
|
|
+ if (mPlayer != null) {
|
|
|
+ long duration = mPlayer.getDuration();
|
|
|
+ return duration;
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void start() {
|
|
|
+ if (isStoped) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // release()会释放player、将player置空,所以这里需要判断一下
|
|
|
+ if (null != mPlayer && hasPrepared) {
|
|
|
+ mPlayer.start();
|
|
|
+ setVolume(isNeedMute ? 0f : 1f);
|
|
|
+ if (prepareSeekPosition > 0) {
|
|
|
+ seekTo(prepareSeekPosition);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setVolume(float volume) {
|
|
|
+ if (mPlayer != null) {
|
|
|
+ LOG.i(TAG,"setVolume:" + volume + "hasPrepared:" + hasPrepared);
|
|
|
+ mPlayer.setVolume(volume, volume);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void pause() {
|
|
|
+ if (null != mPlayer && hasPrepared) {
|
|
|
+ mPlayer.pause();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void seekTo(int position) {
|
|
|
+ if (null != mPlayer && hasPrepared) {
|
|
|
+ mPlayer.seekTo(position);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 对于播放视频来说,通过设置SurfaceHolder来设置显示Surface。这个方法不需要判断状态、也不会改变player状态
|
|
|
+ public void setDisplay(SurfaceHolder holder) {
|
|
|
+ if (null != mPlayer) {
|
|
|
+ mPlayer.setDisplay(holder);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void stop() {
|
|
|
+ if (mPlayer == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ prepareSeekPosition = -1;
|
|
|
+ isStoped = true;
|
|
|
+ hasPrepared = false;
|
|
|
+ Log.i(TAG, "player to stop:" + hasPrepared + "-thread:" + Thread.currentThread().getName());
|
|
|
+ mPlayer.stop();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onCompletion(IMediaPlayer iMediaPlayer) {
|
|
|
+ hasPrepared = false;
|
|
|
+ LOG.i(TAG, "onCompletion");
|
|
|
+ // 通知调用处,调用play()方法进行下一个曲目的播放
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean onError(IMediaPlayer iMediaPlayer, int i, int i1) {
|
|
|
+ hasPrepared = false;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onPrepared(IMediaPlayer iMediaPlayer) {
|
|
|
+ hasPrepared = true; // 准备完成后回调到这里
|
|
|
+ start();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setSpeed(float speed) {
|
|
|
+ Log.i(TAG, "setSpeed:" + speed);
|
|
|
+ try {
|
|
|
+ if (mPlayer != null) {
|
|
|
+ if (speed > Constants.MAX_PLAY_SPEED) {
|
|
|
+ speed = Constants.MAX_PLAY_SPEED;
|
|
|
+ }
|
|
|
+ if (speed < Constants.MIN_PLAY_SPEED) {
|
|
|
+ speed = Constants.MIN_PLAY_SPEED;
|
|
|
+ }
|
|
|
+ mPlayer.setSpeed(speed);
|
|
|
+ mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "soundtouch", 1);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void release() {
|
|
|
+ hasPrepared = false;
|
|
|
+ isStoped = true;
|
|
|
+ mPlayer.stop();
|
|
|
+ mPlayer.release();
|
|
|
+ mPlayer = null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|