在Android中,如何将预定义的Surface传递给MediaCodec进行编码?

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说明了"指定要渲染此解码器输出的Surface"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返回错误:Invalid argument (-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的信息。
2个回答

9
不,不是这样的。输入表面必须使用createInputSurface()创建。
请记住,“表面”不是数据缓冲区,它是一个队列,生产者和消费者端点通常位于不同的进程中。需要设置很多东西。还请注意,SurfaceEGLSurface是两个不相关的东西,尽管经常一起使用。
这个API看起来有些臃肿和奇怪,因为...确实是这样的。多年来Surface的实现已经发生了很大变化——基础设施以前远不如现在通用,所以大多数用于修改端点的API都没有暴露出来。MediaCodec API(规范不足)仍在不断发展。
Grafika中有一个将相同内容(相机预览)呈现给GLSurfaceViewMediaCodec的示例。听起来你正在尝试做类似的事情。(如果不是,请更新你的问题,我会更新答案。)

我能否像使用MediaRecorder一样,在MediaCodec的Surface中放置位图来录制视频?请参见https://dev59.com/v1UK5IYBdhLWcg3wwSLg - user25

1
似乎在API 23及以上版本中,有一个名为setInputSurface(Surface)的API:

API 23+ with setInputSurface(Surface)


请注意,它需要使用MediaCodec的createPersistentInputSurface()调用创建的“持久输入表面”。因此,API更加灵活,但仍必须使用由MediaCodec创建的表面。 - fadden

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