SurfaceHolder/Surface 与 MediaPlayer 异步问题探讨

SurfaceHolder 在主线程通知 Surface 的创建、销毁、变化,一般此时将 Surface 设置给 MediaPlayer,这没有问题。

本文讨论的场景是在另一个线程异步的给MediaPlayer设置Surface会出现什么问题,如果想用独立的状态机线程与 MediaPlayer 协作,这将是一个确实存在的问题。

异步设置 Surface 存在 Surface失效问题。

考虑Surface刚创建又马上销毁,MediaPlayer可能会拿到一个失效的 Surface。

从 SurfaceHolder 实现看,SurfaceHolder 内部的 Surface 对象是一直存在的,不会为 null,但是Surface对象里面连接的 native 层的 Surface 对象可能为 NULL。这也是 SurfaceHolder 通知 Surface 的创建、销毁的原因。

在状态机线程先判断 Surface 是否有效(isValid),在设置给 MediaPlayer,可以降低不同步的概率,但是仍然可能 MediaPlayer 拿到一个失效的 Surface。

另一方面,如果 Surface 销毁,SurfaceHolder 会提前通知,这时候可以让 MediaPlayer 预先处理释放 Surface。SurfaceHolder 通知返回之前,并不会销毁 Surface 。

所以我们可以利用这种机制延迟 Surface 的销毁,通过同步等待状态机线程异步处理完成。但是这种等待发生在 UI 线程,只能短时间等待(个人觉得不应该超过100ms)。所以仍然也可能出现失效问题,但是概率已经大大减低了。

MediaPlayer 能不能处理失效的 Surface。

从线程安全性上看,Surface 是线程安全的,MediaPlayer 拿到 native 层的 Surface 后通过智能引用持有 Surface,Surface 不会释放。但是也可能拿到一个 NULL Surface。MediaPlayer 遇到 NULL Surface 会抛出异常。

更进一步,即使 Surface 非空,也可能 Surface 已经销毁了,Surface 上的 BufferQueue 不存在了,此时,MediaPlayer 也会抛出异常。

如果一切正常,MediaPlayer 会拿到 BufferQueue 的引用(IGraphicBufferProductor),但是 BufferQueue 的  Consumer 会没有连接,导致 mediaserver 端尝试连接 BufferQueue 时发生错误,此时 MediaPlayer 同样会抛出异常。

MediaPlayer 多次释放 Surface 的问题。

事实上,异步方式还会引发 MediaPlayer 的一个多次释放的 BUG, 该 BUG 在正常情况是不太可能存在的。

MediaPlayer 持有一个 IGraphicBufferProductor 的引用,此时再次设置一个 Surface,不幸的是,Surface 失效了。

MediaPlayer 会释放前一个 IGraphicBufferProductor 的引用,但是因为新 Surface 无效,抛出异常,跳过了置空 IGraphicBufferProductor  引用(非智能引用)的步骤。

再次设置一个 Surface,MediaPlayer 再次释放之前的 IGraphicBuferProductor 引用,但是已经是野指针了,程序 SIGENV 或者 SIGBUS 退出。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fighting Horse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值