本篇参考封装一个视频播放器,原文已经写的非常棒了,本篇加入了个人对其内容的理解。秉承不重复造轮子的良好理念,接下来开始拆解轮子。内容非常多,我都差点放弃写,有耐心的请往下看
github上非常棒的视频相关开源项目有:
最炫的哔哩哔哩的ijkplayer
JiaoziVideoPlayer 基于ijkplayer
GSYVideoPlayer 基于ijkplayer
结合前三篇内容,我们已经对MediaPlayer,SurfaceView,TextureView有了基本了解。相比SurfaceView,TextureView的类View特性,使其更加灵活。因此,我们选择TextureView结合MediaPlayer的方式来自定义视频播放器。只要你静下心来,跟着源码一步步敲,慢慢理解,你就会发现原来自定义视频播放器并不难。
核心思想
类似MVC模式
- NiceVideoPlayer:自定义播放界面,其主要是MediaPlayer和TextureView结合,负责视频数据解析和显示。
- NiceVideoController:控制界面,主要是控制暂停,播放,亮度,音量等
- INiceVideoPlayer:接口,定义了视频播放的相关方法,例如播放,暂停,获取当前播放状态等。
INiceVideoPlayer接口
定义接口前我们先思考下我们需要VideoPlayer实现什么功能,给VideoContronller提供哪些方法。
- 播放状态,根据前面的知识我们知道,MediaPlayer有多种状态,我们需要判断MediaPlayer的状态
/******************************
* 以下方判断播放器当前的播放状态
******************************/
boolean isIdle();//是否空闲
boolean isPreparing();
boolean isPrepared();
boolean isBufferingPlaying();
boolean isBufferingPaused();
boolean isPlaying();
boolean isPaused();
boolean isError();
boolean isCompleted();
- 播放模式,基本的播放模式有正常模式,全屏模式,以及小窗口模式
/*************************
* 播放器模式
*************************/
boolean isFullScreen();
boolean isTinyWindow();
boolean isNormal();
/**
* 进入全屏模式
*/
void enterFullScreen();
/**
* 退出全屏模式
* @return
*/
boolean exitFullScreen();
/**
* 进入小窗口模式
*/
void enterTinyWindow();
/**
* 退出小窗口模式
* @return
*/
boolean exitTinyWindow();
- 播放控制
/**
* 开始播放
*/
void start();
/**
* 从指定位置开始播放
*
* @param position 播放位置
*/
void start(long position);
/**
* 重新播放,播放器被暂停,播放错误,播放完成后需要调用这个方法重新播放
*/
void restart();
/**
* 暂停播放
*/
void pause();
/**
* 释放videoPlayer
*/
void releasePlayer();
/**
* 释放
*/
void release();
完整代码
public interface INiceVideoPlayer {
/**
* 设置视频的url,以及headers
*
* @param url 视频地址,可以是本地,也可以是网络
* @param headers 请求header
*/
void setUp(String url, Map<String, String> headers);
/***************
* 播放控制
****************/
/**
* 开始播放
*/
void start();
/**
* 从指定位置开始播放
*
* @param position 播放位置
*/
void start(long position);
/**
* 重新播放,播放器被暂停,播放错误,播放完成后需要调用这个方法重新播放
*/
void restart();
/**
* 暂停播放
*/
void pause();
/**
* 释放videoPlayer
*/
void releasePlayer();
/**
* 释放
*/
void release();
/**
* seek到指定的位置继续播放
*
* @param pos
*/
void seekTo(long pos);
/**
* 开始播放时,是否重上一次的位置继续播放
*
* @param continueFromLastPosition 上次播放位置
*/
void continueFromLastPostion(boolean continueFromLastPosition);
/**
* 获取当前的播放位置
*/
long getCurrentPostion();
/**
* 获取视频缓冲百分比
*/
int getBufferPercentage();
/**
* 设置音量
*
* @param volume 音量值
*/
void setVolume(int volume);
/**
* 获取最大音量
*
* @return
*/
int getMaxVolume();
/**
* 获取当前的音量
*
* @return
*/
int getVolume();
/**
* 获取总时长
*
* @return
*/
long getDuration();
/******************************
* 播放器当前的播放状态
******************************/
boolean isIdle();//是否空闲
boolean isPreparing();
boolean isPrepared();
boolean isBufferingPlaying();
boolean isBufferingPaused();
boolean isPlaying();
boolean isPaused();
boolean isError();
boolean isCompleted();
/*************************
* 播放器模式
*************************/
boolean isFullScreen();
boolean isTinyWindow();
boolean isNormal();
/**
* 进入全屏模式
*/
void enterFullScreen();
/**
* 退出全屏模式
*
* @return
*/
boolean exitFullScreen();
/**
* 进入小窗口模式
*/
void enterTinyWindow();
/**
* 退出小窗口模式
*
* @return
*/
boolean exitTinyWindow();
}
NiceVideoPlayer
定义播放状态,我们知道MediaPlayer在初始化和reset处于 Idle状态即STATE_IDLE。
播放视频时,MediaPlayer准备就绪(Prepared)后没有马上进入播放状态,中间有一个时间延迟时间段,然后开始渲染图像。所以将Prepared——>“开始渲染”中间这个时间段定义为STATE_PREPARED。
如果是播放网络视频,在播放过程中,缓冲区数据不足时MediaPlayer内部会停留在某一帧画面以进行缓冲。正在缓冲时,MediaPlayer可能是在正在播放也可能是暂停状态,因为在缓冲时如果用户主动点击了暂停,就是处于STATE_BUFFERING_PAUSED,所以缓冲有STATE_BUFFERING_PLAYING和STATE_BUFFERING_PAUSED两种状态,缓冲结束后,恢复播放或暂停。
/****************
* 播放状态
****************/
/**
* 播放错误
*/
public static final int STATE_ERROR = -1;
/**
* 播放未开始
*/
public static final int STATE_IDLE = 0;
/**
* 播放准备中
*/
public static final int STATE_PREPARING = 1;
/**
* 播放准备就绪
*/
public static final int STATE_PREPARED = 2;
/**
* 正在播放
*/
public static final int STATE_PLAYING = 3;
/**
* 暂停播放
*/
public static final int STATE_PAUSED = 4;
/**
* 正在缓冲,播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复
*/
public static final int STATE_BUFFERING_PLAYING =5;
/**
* 正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停
**/
public static final int STATE_BUFFERING_PAUSED = 6;
/**
* 播放完成
*/
public static final int STATE_COMPLETED = 7;
播放模式普通模式,全屏模式,小屏模式
/*************
* 播放模式
*************/
/**
* 普通模式
*/
public static final int MODE_NORMAL = 10;
/**
* 全屏模式
*/
public static final int MODE_FULL_SCREEN = 11;
/**
* 小窗口模式
*/
public static final int MODE_TINY_WINDOW =