想着练习下学习下 ijkplayer
,但不知道做个啥,就想着做个今日头条类似的视频播放列表,当item滑出了可视区域就自动播放下一个视频,因为播放器需要opengl渲染,所以就需要glsurfaceview,最开始的思路就是每个item都有一个surfaceview然后新建一个IjkMediaPlayer.使用后发现还没加入播放等动作就已经卡顿的不得了。如下图:

条状图就是手机开启了gpu呈现模式分析(在绿色横线以下就是每帧<=16ms)大于就是有些卡顿了,对于滚动界面来说就有必要优化了。

后来改换思路整个列表只使用一个MyVideoView(glsurfaceview+ijkplayer的整合)

然后通过addview到指定的item中,然后跟随滑动,就普通的addview,removeview这两个操作就已经要60ms左右,这对于一个滑动列表肯定也是不行的,不过相对之前已经有所进步了。


最后想干脆我也不addview进去了,直接新建一个MyVideoView,滑动的时候跟随着滑动,不addview也不用removeview,就简单的跟随滑动,发现要完全滑出了界面,就自动播放下一个item视频。

滑动效果如下:感觉已经能满足需求了(视频的播放暂停,进度条没加入进去,这个不会影响滑动卡顿问题,添加简单所以就没继续写了。)

gif效果图:


现在简单看看代码:
MyVideoView(是GlSurfaceView 和ijkPlayer的封装):
public void play(final String path) { new Thread() { @Override public void
run() { super.run(); synchronized (MyVideoView.class) { try { playRelease();
player = new IjkMediaPlayer(); player.setDisplay(surfaceView.getHolder());
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(path); player.prepareAsync();
player.setOnPreparedListener(new IMediaPlayer.OnPreparedListener() { @Override
public void onPrepared(IMediaPlayer iMediaPlayer) { if (lis != null)
lis.startSuccess(); iMediaPlayer.start(); Log.e("xhc", " start ..."); } }); }
catch (Exception e) { e.printStackTrace(); } } } }.start(); }
将Ijkplayer的释放,新建,都是在子线程中处理的,为的就是不阻塞主线程。

下面来看看recycleview的滑动事件的监听把:
if(currentPosition >= 0 && currentPosition < adapter.getItemCount()){ /** *
1.正在播放的视频已经滑出去,a.自动播放下一条,autoPlay = true b.播放器停止autoPlay = false *
2.正在播放的视频还在可视区域 a.继续播放 */ if(currentPosition <
linearLayoutManager.findFirstVisibleItemPosition() && autoPlay){ //自动播放下一条
lastPosition = currentPosition; currentPosition =
linearLayoutManager.findFirstVisibleItemPosition(); playVideo(currentPosition ,
listVB.get(currentPosition)); } else if(currentPosition >
linearLayoutManager.findLastVisibleItemPosition() && autoPlay){ lastPosition =
currentPosition; currentPosition =
linearLayoutManager.findLastVisibleItemPosition(); playVideo(currentPosition ,
listVB.get(currentPosition)); } else if((currentPosition <
linearLayoutManager.findFirstVisibleItemPosition() || currentPosition >
linearLayoutManager.findLastVisibleItemPosition()) && !autoPlay){
//没有自动播放,如果超出了可视区域直接停止播放器 new Thread(){ @Override public void run() {
super.run(); mv.playRelease(); } }.start(); return ; }
contain.setTranslationY(linearLayoutManager.findViewByPosition(currentPosition).getY());
} }
基本逻辑就是
1.当前播放的视频的position是比当前可视界面的第一个item的position还小,那么就播放下一个
2.如果当前视频的item的position比可视界面的最后一个还大,就播放上条视频。
VideoBean vb = new VideoBean();
vb.setVideoPath("sdcard/FFmpeg/video_src/v1080.mp4"); VideoBean vb2 = new
VideoBean(); vb2.setVideoPath("sdcard/FFmpeg/video_src/test.mp4"); VideoBean
vb3 = new VideoBean(); vb3.setVideoPath("sdcard/FFmpeg/video_src/time.mp4");
VideoBean vb4 = new VideoBean();
vb4.setVideoPath("sdcard/FFmpeg/video_src/input.mp4"); VideoBean vb5 = new
VideoBean(); vb5.setVideoPath("rtmp://58.200.131.2:1935/livetv/hunantv");
VideoBean vb6 = new VideoBean();
vb6.setVideoPath("rtmp://media3.sinovision.net:1935/live/livestream");
测试视频有本地一些mp4和一些rmtp网络流,因为rtmp的网络给予tcp并且自己也要握手,所以加载时间更久点。

视频的测试文件在项目中可看到

这里可以找到测试文件 <https://blog.csdn.net/u010339039/article/details/88719382>

源码地址 <https://github.com/xhc2/MyFFmpeg>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信