- 时间:2022-08-24 01:55 编辑: 来源: 阅读:306
- 扫一扫,手机访问
摘要:安卓播放器硬件解码前后切换黑屏。
[免费源码]
硬件解码的前端和后端切换黑屏最先遇到这个问题。当项目开发Android自定义播放器UI时,需要一个显示视频的列表和一个切换到全屏的小窗口。 从小窗口到全屏有一段时间黑屏,时间不定。 有时快,有时慢。 其实这个问题和硬件解码前后切换黑屏是一样的。 我们知道Android有两个视图用于视频渲染,一个是SurfaceView,一个是TextureView。 至于两者的区别,这里就不赘述了。 查看SurfaceView文档。 首先,这个问题应该怎么描述?其实在正常视频播放的过程中,我是从旧的切换到了新的SurfaceView或者TextureView。 然后导致这种现象。 遇到这个问题,我的第一反应一定是ijkplayer硬件解码切换Surface时,清空了硬件解码器中的缓存帧,导致新的视频帧发送到硬件解码器无法解码。 你需要等待下一个GOP IDR帧序列的到来才能正常解码。 ijkplayer的硬件解码实现是在MediaCodec配置的时候可以设置一个表面,这样硬件解码后的图像就可以直接渲染到表面,不需要内存拷贝,性能更加优异。 当然也可以不设置Surface进行配置,这样可以直接得到解码后的数据,然后用OpenGL ES自己渲染。 参考:MediaCodec文档 看了ijkplayer硬件解码实现的流程,由于Android MediaCodec不支持Surface的动态设置,所以每当设置的显示不是同一个Surface时,ijkplayer的硬件解码实现直接重新创建一个新的MediaCodec。可以直接查看下面的函数实现:static int reconfigure _ codec _ l(JNI env * env,ijkff _ pipenode * node,JobNew _ Surface) IJK播放器硬件解码实现相关代码不过,本文不是讲解【MediaCodec】相关文章(https://developer . Android . com/reference/Android/media/media codec . html),这里只是简单讲解一下。 Android 6.0升级了新的API,支持直接设置Surface。 void[SetOutputSurface]((https://developer . Android . com/reference/Android/view/Surface . html)surface)(surface),但不支持先设置NULL再设置surface。这样前端切换的问题应该暂时没有。 原因已经找到了,那么如何处理这个问题呢?首先不能用SurfaceView来处理这个问题,前后端切换会有一个破坏和创建的过程。 如上所述,Android上显示的另一个视频是TextureView,然后我很自然地想到会创建一个SurfaceTexture。 我们可以使用SurfaceTexture创建一个表面,然后在MediaCodec配置时使用这个表面。 构造函数如下:surface(Android . graphics . surface texture))([surface texture]surface texture)下面两个事件大家应该都不陌生:【onsurfacetexture available】(https://developer.android.com/reference/android/view/TextureView.surface texture listener . html # onSurfaceTextureAvailable(Android . graphics . surface texture,int,Int))(表面纹理surface,int width,Int height)boolean onsurfacetexture destroyed(表面纹理surface)然后怎么操作?当我们进入后端时,onSurfaceTextureDestroyed事件设置return fale并保存SurfaceTexture,这将手动接管SurfaceTexture的生命周期。 然后在通过复制创建TextureView时调用成员函数:void setSurfacetexture(表面纹理Surfacetexture),从而解决MediaCodec的表面设置问题。 解决办法是不要换。 其实在ijkplayer的官方演示中有相关的样例代码 但是很多人就是不明白为什么。