【问题标题】:Decode H.264 stream using MediaCodec API JNI使用 MediaCodec API JNI 解码 H.264 流
【发布时间】:2015-12-04 00:25:18
【问题描述】:

我正在使用 MediaCodec API 开发 H.264 解码器。我正在尝试在 JNI 层中调用 MediaCodec java API,例如:

void Decompress(const unsigned char *encodedInputdata, unsigned int inputLength, unsigned char **outputDecodedData, int &width, int &height) {
    // encodedInputdata is encoded H.264 remote stream
    // .....
    // outputDecodedData = call JNI function of MediaCodec Java API to decode
    // .....
}

稍后我会将outputDecodedData 发送到我现有的视频渲染管道并在Surface 上进行渲染。

我希望我能够编写一个 Java 函数来解码输入流,但这将是一个挑战 -

  1. resource 声明 -

...你不能对解码的视频帧做任何事情,但要渲染它们 浮出水面

这里Surface 已传递decoder.configure(format, surface, null, 0) 以在表面上渲染输出ByteBuffer 并声明We can't use this buffer but render it due to the API limit

那么,我能否将输出 ByteBuffer 发送到本机层以转换为 unsigned char* 并传递给我的渲染管道,而不是传递 Surfaceconfigure()

【问题讨论】:

    标签: android c++ android-mediacodec


    【解决方案1】:

    我发现您提出的函数定义存在两个基本问题。

    首先,MediaCodec 对访问单元(H.264 的 NAL 单元)进行操作,而不是流中的任意数据块,因此您需要一次传入一个 NAL 单元。一旦接收到块,编解码器可能希望在产生任何输出之前等待额外的帧到达。通常,您不能传递一帧输入并等待接收一帧输出。

    其次,正如您所指出的,ByteBuffer 输出以几种颜色格式之一进行了 YUV 编码。格式因设备而异;高通设备尤其使用自己的专有格式。 (不过,它已经过逆向工程,所以如果你四处搜索,你可以找到一些代码来解开它。)

    常见的解决方法是将视频帧发送到 SurfaceTexture,然后将它们转换为 GLES“外部”纹理。这些可以通过各种方式进行操作,或者呈现到 pbuffer 并使用 glReadPixels() 提取。

    【讨论】:

    • 谢谢先生!因此,目前我正在使用自定义侦听器从本机层接收 H.264 的 NAL 单元到 Java 层,并尝试使用 MediaCodec 将其解码到 SurfaceTextureView)上。让我们看看我能走多远! :)
    • 谢谢您的链接!幸好我熟悉H.264结构,使用ffmpeg、openh264等第三方专有库在native层实现了编解码功能。如果我需要顾问(像你一样)的建议,我希望我能让它发挥作用,并会在 SO 上打开新线程 :)
    • 先生,我试过了,现在遇到了一些问题。你能看看这个线程吗? stackoverflow.com/questions/32723393/…
    猜你喜欢
    • 2013-04-07
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 2015-12-19
    • 2012-11-07
    • 2012-06-22
    • 2015-12-12
    相关资源
    最近更新 更多