BaseVideoView.java 10.2 KB
package com.cnlive.gundam.video.view;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.RelativeLayout;

import com.cnlive.gundam.R;
import com.cnlive.gundam.databinding.LayoutVideoViewBinding;
import com.cnlive.gundam.video.model.DataSource;
import com.cnlive.gundam.video.model.VideoModel;
import com.cnlive.libs.util.Config;
import com.cnlive.libs.util.SharedPreferencesHelper;
import com.cnlive.libs.video.video.VideoStatusUtil;
import com.cnlive.libs.video.video.base.IMediaPlayer;
import com.cnlive.libs.video.video.base.ISwitchVideoView;
import com.cnlive.libs.video.video.base.IVideoStatus;

/**
 * Created by gujun on 2017/4/5.
 * 这个里只是关于播放器和ugc直播播放状态的相关处理
 */

public abstract class BaseVideoView extends RelativeLayout implements
        IMediaPlayer.OnCompletionListener, IMediaPlayer.OnInfoListener,
        IMediaPlayer.OnErrorListener, IMediaPlayer.OnPlayStateListener,
        IMediaPlayer.OnSeekCompleteListener, IMediaPlayer.OnPreparedListener,
        IMediaPlayer.OnBufferingUpdateListener, ISwitchVideoView.OnSwitchVideoPreparedListener,
        ISwitchVideoView.OnSwitchVideoErrorListener, ISwitchVideoView.OnSwitchVideoCompleteListener {

    protected LayoutVideoViewBinding binding;

    //记录当前视频播放状态
    protected boolean isPlay = false;
    //当前播放器的播放进度 重试的时候从此时间播放
    private long curPlayPosition = -1;
    //prepare后是否seekTo 为了重试后seekComplete过滤
    private boolean isPrepareSeek = false;

    //播放数据
    protected VideoModel videoModel;
    //记录当前是否是直播节目
    protected static boolean isLive;
    //记录当前视频是否能播
    protected boolean canPlay = true;
    //本地缓存数据工具类
    private SharedPreferencesHelper sharedPreferencesHelper;
    //播放进度保存至本地缓存的标识前缀
    private final String CUR_PLAY_POSITION_PRE = "CurPlayPosition_";
    //保存切换码率之前的码率
    private String preRate = Config.TYPE_PLAY_RATE_2;
    //保存当前要切换的码率
    private String curRate = "";
    //记录当前是否正在切换视频
    protected boolean switchingVideoRate = false;

    private DataSource curDataSource;

    private OnVideoViewPlayStatusListener l;

    public BaseVideoView(Context context) {
        this(context, null);
    }

    public BaseVideoView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BaseVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public void setVideoViewPlayStatus(OnVideoViewPlayStatusListener listener) {
        l = listener;
    }

    protected void init() {
        sharedPreferencesHelper = SharedPreferencesHelper.getInstance(getContext());
        binding = DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.layout_video_view, this, true);
        binding.videoView.setOnPreparedListener(this);
        binding.videoView.setOnInfoListener(this);
        binding.videoView.setOnErrorListener(this);
        binding.videoView.setOnCompletionListener(this);
        binding.videoView.setOnSeekCompleteListener(this);
        binding.videoView.setOnPlayStateListener(this);
        binding.videoView.setOnBufferingUpdateListener(this);
        binding.videoView.setScreenOnWhilePlaying(true);
        binding.videoView.setOnSwitchVideoPreparedListener(this);
        binding.videoView.setOnSwitchVideoErrorListener(this);
        binding.videoView.setOnSwitchVideoCompleteListener(this);
        setKeepScreenOn(true);
    }

    public void setDataSource() {
        //只有ugcLive视频才有状态监听
        if (videoModel.getType().equals(VideoView.TYPE_UGC_LIVE)) {
            VideoStatusUtil.setOnVideoPlayStatusCallback(mOnVideoStatusCallback);
            VideoStatusUtil.init(videoModel.getId());
        }

        if (isLive) {
            curPlayPosition = -1;
            binding.videoView.setDataSource(curDataSource = new DataSource(videoModel.getId(), Config.TYPE_LIVE, Config.TYPE_PLAY_RATE_2));
        } else {
            curPlayPosition = sharedPreferencesHelper.getLong(CUR_PLAY_POSITION_PRE + videoModel.getId());
            binding.videoView.setDataSource(curDataSource = new DataSource(videoModel.getId(), Config.TYPE_VOD, Config.TYPE_PLAY_RATE_2));
        }

        preRate = Config.TYPE_PLAY_RATE_2;


    }

    /**
     * 设置当前播放进度
     *
     * @param curPosition
     */
    protected void setPlayPosition(long curPosition) {
        curPlayPosition = curPosition;
    }

    public void onResume() {
        if (!binding.videoView.isPlaying() && isPlay) {
            setPlayState(true);
        }
    }

    public void onPause() {
        if (binding.videoView.isPlaying()) {
            setPlayState(false);
        }
    }

    public void onDestroy() {
        binding.videoView.releaseSwitchVideo();
        binding.videoView.release();
        VideoStatusUtil.quit();
        saveCurPlayPosition();
    }

    //保存当前播放视频的播放进度
    protected void saveCurPlayPosition() {
        if (!isLive && curDataSource != null && sharedPreferencesHelper != null) {
            sharedPreferencesHelper.setValue(CUR_PLAY_POSITION_PRE + curDataSource.getDataSourceId(), curPlayPosition);
        }
    }

    protected void retry() {
        binding.videoView.reload();
    }

    protected void replay() {
        isPrepareSeek = true;
        binding.videoView.seekTo(0);
    }

    /**
     * 设置播放状态
     *
     * @param isPlay
     */
    protected void setPlayState(boolean isPlay) {
        if (isPlay) binding.videoView.start();
        else binding.videoView.pause();
    }

    /**
     * 播放按钮点击
     */
    public void playBtnClick() {
        isPlay = !isPlay;
        setPlayState(isPlay);
    }

    /**
     * 切换视频码率
     *
     * @param rate
     */
    public void switchVideoRate(String rate) {
        //TODO 换成无缝切换
        curRate = rate;
        if (binding.controllerView != null)
            binding.controllerView.setSwitchRateType(PlayerControllerView.SWITCH_RATE_START, curRate);
        curDataSource.setRate(rate);
        if (binding.videoView != null)
            binding.videoView.switchVideo(curDataSource);
    }


//----------------------播放器相关回调 start-------------------------------

    @Override
    public void onCompletion(IMediaPlayer iMediaPlayer) {
        isPlay = false;
    }

    @Override
    public boolean onError(IMediaPlayer iMediaPlayer, int i, int i1) {
        isPlay = false;
        return false;
    }

    @Override
    public boolean onInfo(IMediaPlayer iMediaPlayer, int i, int i1) {
        return false;
    }

    @Override
    public void onPlayState(boolean isPlay) {
        if (l != null) l.onVideoViewPlayStatus(isPlay);
    }

    @Override
    public void onPrepared(IMediaPlayer iMediaPlayer) {
        if (curPlayPosition > 0) {
            isPrepareSeek = true;
            iMediaPlayer.seekTo(curPlayPosition);
        } else {
            if (canPlay && !iMediaPlayer.getPlayState()) {
                setPlayState(true);
                isPlay = true;
            }
        }
    }

    @Override
    public void onSeekComplete(IMediaPlayer iMediaPlayer) {
        if (!isPrepareSeek) return;
        isPrepareSeek = false;
        setPlayState(true);
        isPlay = true;
    }

    @Override
    public void onBufferingUpdate(IMediaPlayer iMediaPlayer, int i) {

    }


    @Override
    public void onSwitchVideoError(IMediaPlayer iMediaPlayer, int i, int i1) {
        binding.videoView.releaseSwitchVideo();
        switchingVideoRate = false;
        //切换失败继续播切换之前的码率
        curDataSource.setRate(preRate);
        if (binding.controllerView != null) {
            binding.controllerView.setCurRate(preRate);
            binding.controllerView.setSwitchRateType(PlayerControllerView.SWITCH_RATE_ERROR, curRate);
        }
    }

    @Override
    public void onSwitchVideoComplete(IMediaPlayer iMediaPlayer) {
        switchingVideoRate = false;
        if (binding.controllerView != null)
            binding.controllerView.setSwitchRateType(PlayerControllerView.SWITCH_RATE_FINISH, curRate);
        preRate = curRate;
    }

    @Override
    public void onSwitchVideoPrepared(IMediaPlayer iMediaPlayer) {
        switchingVideoRate = true;
        if (binding.videoView != null) {
            binding.videoView.switchVideoStart(binding.videoView.getCurrentPosition());
        }
    }


//    ---------------------ugc直播状态的回调---------------------------------

    private IVideoStatus.VideoStatusCallback mOnVideoStatusCallback = new IVideoStatus.VideoStatusCallback() {
        @Override
        public void onStatusChange(int status) {
            switch (status) {
                case IVideoStatus.MEDIA_STATUS_LIVING:
                    //直播中'
                    canPlay = true;
                    if (!binding.videoView.getPlayState()) {
                        binding.videoView.reload();
                        binding.infoView.show(PlayerInfoView.SHOW_BUFFERING);
                    }
                    break;
                case IVideoStatus.MEDIA_STATUS_LEAVE:
                    //主播暂时离开
                    canPlay = false;
                    binding.videoView.stop();
                    binding.infoView.show(PlayerInfoView.SHOW_UGC_LIVE_STATUS, getContext().getString(R.string.player_status_leave));
                    break;
                case IVideoStatus.MEDIA_STATUS_END:
                    //直播结束
                    canPlay = false;
                    binding.videoView.stop();
                    binding.infoView.show(PlayerInfoView.SHOW_UGC_LIVE_STATUS, getContext().getString(R.string.player_status_end));
                    break;
            }

        }

        @Override
        public void onError(int what, String extra) {
            Log.e("ugcLive status", "onError: " + extra);
        }
    };

    //播放器播放状态监听
    public interface OnVideoViewPlayStatusListener {
        void onVideoViewPlayStatus(boolean isPlay);
    }
}