微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

android-MediaCodec同时编码和解码

我正在尝试使用GPU将效果应用于视频的帧,然后将这些帧重新编码为新的结果视频.

为了提高性能,我实现了以下流程:

有3个不同的线程,每个线程都有自己的OpenGL上下文.这些上下文的设置方式使它们可以在它们之间共享纹理.

线程1从视频中提取帧并将其作为纹理保存在GPU内存中,类似于this示例.

线程2使用修改后的GPUImage版本处理纹理,该版本还可以在GPU内存中输出纹理.

最后,线程3将从线程2获得的纹理写入新的视频文件中,类似于here中描述的方法.

使用线程1和2之间以及线程2和3之间的队列来维护帧顺序.将纹理用于处理/写入之后,将其从内存中手动删除.

该流程的重点是将每个进程分开,以期最终性能将是3个线程中最慢的一个.

问题:

最终的视频是90%的黑帧,只有其中一些是正确的.

我检查了提取和处理的各个结果,它们均按预期工作.还要注意,在3个线程中描述的3个组件在单个线程中可以很好地协同工作.

我试图同步线程1和线程3,并且在线程1上增加了100ms的睡眠时间后,视频结果还不错,可能有1或2个黑帧.在我看来,解码器和编码器的两个实例无法同时工作.

我将使用任何其他要求的详细信息来编辑此帖子.

解决方法:

在OpenGL ES上下文之间共享纹理需要格外小心.在Grafika’s显示捕获摄像机”中的实现方式活动已中断;有关详细信息,请参见this issue.基本的问题是,在更新纹理时,您基本上需要发出内存屏障.实际上,这意味着在生产者端发出glFinish(),然后在消费者端重新绑定纹理,并在同步块中完成所有这些操作.

如果您可以在单个线程上完成所有的GLES工作,那么您的生活将变得更加简单(高效).以我的经验,一次激活多个GLES上下文是不明智的,并且通过找到替代方法可以避免一些麻烦.

您可能想要更多这样的东西:

>线程1读取文件并将帧馈送到MediaCodec解码器中.解码器将输出发送到SurfaceTexture Surface.
>线程2具有GLES上下文.它创建了线程1将输出发送到的SurfaceTexture.它处理图像并将输出呈现在MediaCodec编码器的Surface上.
>创建MediaCodec编码器的线程#3坐在那里等待编码输出.接收到输出后,将其写入磁盘.请注意,使用Mediamuxer可能会拖延;有关更多信息,请参见this blog post.

在所有情况下,线程之间(以及内部进程)之间的唯一通信是通过Surface完成的. SurfaceTexture和MediaCodec实例是从单个线程创建和使用的.只有生产者端点(Surface)被传递.

流量控制是一个潜在的麻烦点-如果过快地喂入它们,SurfaceTextures会掉落帧.根据情况,组合线程#1和#2可能有意义.

原文地址:https://www.jb51.cc/android/1053077.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐