繁体   English   中英

MediaCodec同时编码和解码

[英]MediaCodec simultaneous encoding and decoding

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

为了表现,我实施了以下流程:

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

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

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

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

使用线程1和线程2以及线程2和3之间的队列维护帧顺序。纹理用于处理/写入之后手动从存储器中删除。

这个流程的重点是将每个进程分开,希望最终的性能是3个线程中最慢的。

问题:

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

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

我试图同步线程1和线程3,并在为线程1添加额外的100ms休眠时间后,视频结果很好,可能有1或2个黑帧。 在我看来,解码器和编码器的两个实例无法同时工作。

我将使用任何额外请求的详细信息编辑此帖子。

在OpenGL ES上下文之间共享纹理需要一些小心。 它在Grafika的 “show + capture camera”活动中实施的方式被打破了; 有关详细信息,请参阅此问 基本问题是你在更新纹理时基本上需要发出内存障碍; 实际上,这意味着在生产者方面发布glFinish() ,并在消费者方面重新绑定纹理,并在synchronized块中执行所有这些操作。

如果您可以在单个线程上完成所有GLES工作,那么您的生活将变得更简单(也更高效)。 根据我的经验,一次有多个GLES上下文是不明智的,你可以通过寻找替代方案来省去一些痛苦。

你可能想要更像这样的东西:

  • 线程#1读取文件并将帧馈送到MediaCodec解码器。 解码器将输出发送到SurfaceTexture Surface。
  • 线程#2具有GLES上下文。 它创建了线程#1将输出发送到的SurfaceTexture。 它处理图像并在MediaCodec编码器的Surface上呈现输出。
  • 创建MediaCodec编码器的线程#3等待编码输出。 收到输出后,它会写入磁盘。 请注意,MediaMuxer的使用可能会停滞; 有关更多信息 ,请参阅此博文

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

一个潜在的问题在于流量控制 - 如果您过快地提供帧,SurfaceTextures将丢弃帧。 根据情况,组合线程#1和#2可能有意义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM