Android视频:更改视觉属性(例如饱和度、亮度)

6
假设我们在Android中有一个显示视频(例如h264)的Surface,并使用MediaPlayer:
1)是否可以实时更改表面上显示的视频的饱和度、对比度和亮度?例如,图像可以使用setColorFilter,在Android中是否有类似的处理视频帧的方法?
或者如果第一条太难:
2)如果我们想要导出具有增加饱和度的视频,我们应该使用编解码器,例如MediaCodec。在进行编解码器/保存操作之前,应使用什么技术(方法、类、库等)来应用饱和度变化?

你是想要一个现成的库来处理视频显示(如下面的答案所示),还是有其他要求不允许使用该库?答案中链接的项目演示了如何使用GLSurfaceViewMediaPlayer,并应用OpenGL着色器在显示上执行过滤。如果您不需要导出经过滤镜处理的视频,则这绝对是一个合理的方法。那么你现在的Surface从哪里来? - Dave
嗨@Dave,我目前正在调查如何调整显示的视频(通常在表面上),同时也导出已调整的视频。所以我没有具体的“Surface” - 这就是我正在寻找的 :) - Diolor
2个回答

2
仅用于显示的一种简单方法是使用 GLSurfaceView,一个 SurfaceTexture 来渲染视频帧,以及一个 MediaPlayer。 Prokash 的答案链接到一个开源库,展示了如何完成这个过程。如果你搜索这些术语,还有许多其他例子。采用这种方法,您可以将视频帧绘制到 OpenGL 纹理中,并创建 OpenGL 着色器来操作纹理的渲染方式。(我建议向 Prokash 询问更多详细信息,并接受他的答案,如果这足以满足您的要求。)
同样地,您可以使用OpenGL工具与MediaCodecMediaExtractor一起解码视频帧。 MediaCodec将被配置为输出到SurfaceTexture,因此您不需要做太多的工作来编写一些样板代码以使输出缓冲区呈现。过滤过程与MediaPlayer相同。有许多使用MediaCodec作为解码器的示例可用,例如这里这里。使用Prokash示例中的GLSurfaceView替换这些示例中使用的TextureViewSurfaceView应该是相当简单的。
这种方法的优点是您可以访问媒体文件中的所有单独轨道。因此,您应该能够使用OpenGL过滤视频轨道,并将其他轨道直接复制以进行导出。您将使用MediaCodec处于编码模式,使用来自GLSurfaceViewSurface作为输入,以及一个MediaMuxer将其全部放回一起。您可以在BigFlake上看到几个相关示例。
您可以使用没有SurfaceMediaCodec直接访问解码后的字节数据并以这种方式操纵它。这个示例说明了这种方法。您可以操纵数据并将其发送到编码器进行导出或按您所需呈现。处理原始字节数据时存在一些额外的复杂性。请注意,我喜欢这个示例,因为它说明了如何分别处理音频和视频轨道。
你还可以使用FFMpeg,无论是在本机代码中还是通过其中一个Java包装器。这个选项更适合于导出而不是立即播放。请参见此处此处以获取一些试图使FFMpeg可用于Java的库。它们基本上是命令行界面的包装器。您需要做一些额外的工作来通过FFMpeg管理播放,但这确实是可行的。
如果您有问题,请随时提问,我会尽力阐述对于您的用例最有意义的选项。

嗨,Dave,你的回答绝对值得获得奖励,因为它非常具有分析性。创建视觉过滤器并导出它们的最平衡解决方案似乎需要手动使用MediaCodec。当然,我正在寻找是否可以使用FFMpeg(看起来很棒)并具有一些“预览”功能。谢谢! - Diolor

1
如果您使用支持视频滤镜的播放器,则可以这样做。例如VLC,它是基于FFMPEG[1]构建的。VLC相当容易编译为Android。然后,您所需的只是libvlc(aar文件),就可以构建自己的应用程序。请参见编译说明此处。您还需要编写自己的模块。只需复制现有模块并进行修改即可。不用说,VLC提供了强大的转码和流媒体功能。尽管VLC for Android非常强大,但它有一个巨大的缺点-视频滤镜无法与硬件解码(仅限Android)一起工作。这意味着整个视频处理都在CPU上。
您的另一个选择是使用GLSL / OpenGL在像GLSurfaceView和TextureView这样的表面上。这保证了GPU的功率。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接