15

我有一个管理自己的 GLSurfaceView 的应用程序,现在我想使用 Android 4.3 的新 MediaCodec 功能,该功能将 Surface 作为输入。

在我见过的所有示例中,Surface 都是使用 MediaCodec.createInputSurface() 创建的,然后为此 Surface 创建 GL 上下文。这让人感觉很单一,而且很难将其改造成已经稳定的代码库。

是否可以改用 MediaCodec.configure(format, a_predefined_Surface, null, MediaCodec.CONFIGURE_FLAG_ENCODE) ?这允许我以即插即用和按需的方式使用 MediaCodec。MediaCodec.configure() 采用 Surface 参数的事实表明这应该是可能的。但是,API 声明“指定在其上呈现此解码器输出的表面” http://developer.android.com/reference/android/media/MediaCodec.html#configure(android.media.MediaFormat , android. view.Surface, android.media.MediaCrypto, int) 这是否意味着这仅用于解码而不是编码?. 如果是这样,有没有办法让 MediaCodec 使用预定义的 Surface 进行编码?

我传入的 Surface 已经创建,EGL_RECORDABLE_ANDROID 设置为 true,并且返回的 GL 上下文经过验证包含所需的 EGL_RECORDABLE_ANDROID 属性。尽管如此,MediaCodec.configure() 失败并出现无用异常“native_window_api_connect 返回错误:无效参数 (-22)”:

I/ACodec(32383):  Now uninitialized
I/OMXClient(32383): Using client-side OMX mux.
I/ACodec(32383): [OMX.qcom.video.encoder.avc] Now Loaded
E/MediaCodec(32383): native_window_api_connect returned an error: Invalid argument (-22)
W/System.err(32383): java.lang.IllegalStateException
W/System.err(32383):    at android.media.MediaCodec.native_configure(Native Method)
W/System.err(32383):    at android.media.MediaCodec.configure(MediaCodec.java:259)
[...]
W/System.err(32383):    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1520)
W/System.err(32383):    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1248)

这是来自带有 Android 4.3 的三星 Galaxy S4。

4

2 回答 2

9

不,它不是那样工作的。输入表面必须使用createInputSurface().

请记住,“表面”不是数据缓冲区,它是一个缓冲区队列,生产者和消费者端点通常位于不同的进程中。有很多移动部件需要设置。另请注意,SurfaceandEGLSurface是两个不同的东西,虽然经常一起使用,但并不密切相关。

API 看起来很笨拙而且很奇怪,因为……确实如此。多年来,实现Surface已经发生了相当大的变化——过去的基础远没有那么通用,因此大多数用于更改端点的 API 都没有公开。(未指定的)MediaCodecAPI 仍在不断发展。

有一个在Grafika中展示相同内容(相机预览)GLSurfaceView的示例。听起来你正在尝试做类似的事情。(如果没有,请更新您的问题,我会更新答案。)MediaCodec

于 2014-01-07T16:32:38.513 回答
1

似乎在 API 23+ 中有一个名为 setInputSurface(Surface) 的 API:

API 23+ 与 setInputSurface(Surface)

于 2015-11-04T07:18:00.623 回答