MediaPlayer + SurfaceView 播放视频的时候,播放下一个视频时 surface 会停留在上一帧图像,正常播放情况无影响,因为马上新的视频帧就会输出上去。
但是有时候部分视频格式支持有问题,导致只能输出音频流,没有视频帧输出,就会出现问题。因为这时候 surface 上的图像是上一个视频文件的,但其实播放的是现在的视频文件。这就需要我们清空 surface 内容设置为黑色了。循着这条思路在网上搜索了一圈找到一些方法如下。
https://www.cnblogs.com/roger-yu/p/14963069.html
https://zhuanlan.zhihu.com/p/361812100
这里面的方法都是通过 GLES 来做清除操作,因为直接在 surface 上面操作的话会导致后续的 mediaplayer 播放报错。但是我在 android10 上面使用并没有效果。这条路没法通了。
后续找到 ExoPlayer 也存在相关问题,见问题链接https://github.com/google/ExoPlayer/issues/1942
看解决方案是设置一个黑色占位 View,等待视频渲染后隐藏即可。接着按照这条方法继续寻找,发现 surface 和 mediaplayer 里面并没有直接提供获取渲染第一帧相关的方法。但是MediaPlayer
有一个setOnVideoSizeChangedListener
方法是可以做到的。这个方法注释是Register a callback to be invoked when the video size is known or updated.
。在视频帧不可用的时候是不会被调用的,而且方法会调用两次,分别是onPrepared
回调前后,这样我们就可以实现在播放视频前,展示一个黑色界面遮盖Surface
,视频开始播放且有视频帧时隐藏这个界面。这样从用户视角上来讲,这个上一帧的图像也就完全不可见了。我们也就解决了这个问题。
现在发现不少问题都是这样,并不能从根本上去解决,但是从发现方用户方入手,从体验上解决这个问题,这也不失为一个好的解决思路。