「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」
硬解码H264黑屏的问题
有一个硬解码h264的项目,在播放H264码流时,同时切换app或者将app退出后台,会出现几秒种的黑屏,本篇文章针对这个问题做一种解决方案。
现象
应用程序在播放时,只要进入后台,再返回,就会黑屏几秒,几秒后播放正常。
原始代码思路
用SurfaceView
作为显示图像的载体,在SurfaceView
创建成功时初始化解码器,用TCP接收H264码流,接收到的码流通过解码器解码并显示在SurfaceView
上。
很简单的逻辑,也没什么问题,但是测试后发现,应用程序置于后台时,总有几秒种的黑屏。
尝试去搜索资料,发现大家都不用SurfaceView
作为显示的载体了,而使用另外一种TextureView
进行显示。看见大家都用TextureView
去作为显示载体之后,控制生命周期不进行释放,才恍然大悟。
参考地址:
Android 使用MediaCodec实现视频的无缝切换
SurfaceView和MediaCodec搭配使用退到后台黑屏的问题(应用切换等情况)
解决办法
出现问题的根本原因是因为 在后台之后,会销毁surface
所以我们需要控制不被销毁,不释放。
我们使用TextureView
来作为显示视图的组件,它可以设置生命周期的监听setSurfaceTextureListener
,实现TextureView.SurfaceTextureListener
这个接口后,拿到下面的回调方法,重点逻辑就在回调方法中。
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
// 生效
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// 改变
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
// 销毁
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// 更新
}
应用退出后台时,会执行onSurfaceTextureDestroyed
的回调方法,在该方法中
mSurfaceTexture = surface
mSurfaceTexture 是全局变量
应用回到播放界面时,会执行onSurfaceTextureAvailable
方法,在该方法中
if(mSurfaceTexture != null){ mTextureview.setSurfaceTexture(mSurfaceTexture);
将MediaCodeC和显示载体绑定
使用SurfaceView
时是这样进行绑定
mCodec.configure(format, mSurfaceView.getHolder().getSurface(),
null, 0);
使用TextureView
后
mCodec.configure(format, getSurface(),
null, 0);
...
public Surface getSurface() {
if (mSurface == null) {
mSurface = new Surface(mTextureview.getSurfaceTexture());
}
return mSurface;
}