美文网首页多媒体科技Android 播放器Andorid的好东西
Android 播放器硬解前后台切换黑屏问题

Android 播放器硬解前后台切换黑屏问题

作者: TinyTina | 来源:发表于2017-06-29 12:13 被阅读1102次
    Android 硬解前后台切换黑屏

    首先遇到这个问题的是项目开发Android 定制播放器UI的时候,需要列表显示视频且需要小窗口切换到全屏。遇到了小窗口到全屏的时候有黑屏一段时间,且时间不定。有时候飞快有时候很慢。其实这个问题和硬解前后台切换黑屏问题是同一个问题。
    我们知道Android 进行视频渲染的View 有2个,一个是SurfaceView 另一个是TextureView。至于它们之间的区别这里不再进行描述。请查看SurfaceView文档


    首先这个问题应当如何进行描述?其实就是正常播放视频的过程中从一个旧的切换到了新的SurfaceView 或者TextureView。然后导致这个现象。
    当我遇到这个问题的时候,第一反应肯定是ijkplayer 硬解的时候切换Surface 的时候清空了硬件解码器中的缓存帧导致新的视频帧送到硬件解码器中无法解码。需要等待下一个GOP IDR 帧序列的到来,才能正常解码。
    ijkplayer的硬解实现是在MediaCodec configure 的时候可以设置一个Surface 这样硬解后图像不需要内存拷贝可以直接渲染到Surface 上面,这样性能更加优秀。当然也可以configure 的时候不设置Surface 这样可以直接拿到解码后的数据,然后自己用OpenGL ES 渲染。
    资料参考:MediaCodec 文档
      经过阅读ijkplayer硬解实现的过程,因为Android MediaCodec 不支持动态设置Surface,ijkplayer 硬解实现是直接每当设置display 不是同一个Surface 的时候直接重新创建了新的MediaCodec.
    可以直接查看下来的函数实现:

    static int reconfigure_codec_l(JNIEnv *env, IJKFF_Pipenode *node, jobject new_surface)

    ijkplayer 硬解实现相关代码


    然本篇并非讲解[MediaCodec]相关文章(https://developer.android.com/reference/android/media/MediaCodec.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创建一个Surface ,然后MediaCodec configure 时候用这Surface。构造函数如下:

    Surface(android.graphics.SurfaceTexture))([SurfaceTexture]surfaceTexture)


    下面这个2个事件大家应该很熟悉:

    [onSurfaceTextureAvailable](https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener.html#onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int))(SurfaceTexture surface, int width, int height)
    boolean onSurfaceTextureDestroyed (SurfaceTexture surface)

    然后怎么操作呢?当我们进入后台的时候 onSurfaceTextureDestroyed 事件设置 return fale 并保存 SurfaceTexture,这样将手动接管SurfaceTexture 生命周期。然后当重现创建TextureView的时候调用成员函数:

    void setSurfaceTexture (SurfaceTexture surfaceTexture)

    这样就解决了有关MediaCodec 设置Surface 的问题了。解决的方案是不切换
    其实ijkplayer 官方的demo 中有相关示例代码。不过很多人不了解其中的缘由而已。

    相关文章

      网友评论

        本文标题:Android 播放器硬解前后台切换黑屏问题

        本文链接:https://www.haomeiwen.com/subject/ybhycxtx.html