Android MediaCodec - 通过JNI解释YUV420SP缓冲区

时间:2017-04-19 10:27:09

标签: android c java-native-interface mediacodec yuv

我使用Android的MediaCodec类解码MP4 h.264视频,提取每个ByteBuffer并尝试转换为RGB,以便我们可以在其他地方使用它。

dequeueOutputBuffer()收到有效的缓冲区索引并抓取ByteBuffer之后,我们正在使用JNI中的GetDirectBufferAddress()来获取C代码中的缓冲区,以便我们可以进行转换在那一边。但是出于某些原因,当我们查看大小值和字节布局时,缓冲区看起来似乎没有意义。

根据上一次COLOR_FormatYUV420SemiPlanar返回dequeueOutputBuffer(),我正在给出的MediaFormat显然是MediaCodec.INFO_OUTPUT_FORMAT_CHANGED - 后面是完整的MediaFormat字符串。

VideoDecoder: decoder output format changed: {image-data=java.nio.ByteArrayBuffer[position=0,limit=80,capacity=80], mime=video/raw, crop-top=0, crop-right=1279, slice-height=720, color-format=21, height=720, width=1280, what=1869968451, crop-bottom=719, crop-left=0, stride=1280}

视频的尺寸为1280 * 720,在YUV420SP中我们期望每像素12位 - 我们从中计算出预期的缓冲区大小为1382400字节。但是,当我们从GetDirectBufferAddress()检索缓冲区时,GetDirectBufferCapacity()返回的大小为1433600。

看起来很奇怪的另一件事是该缓冲区中的字节位置。当我们(据说)看到单个颜色的帧时,我们会看到三个不同的Y,U和V值块 - 而不是Y的不同块,然后是U和V的交替值块。 MediaFormat告诉我们,这没有意义。

谁能告诉我们数学出错的地方?还是我们检索价值的方式?或者我们忽略了缓冲区或颜色格式?

编辑:我们的目标是API级别19.调试代码时使用的设备是Asus的Google Nexus 7,运行Android 6.0.1。

1 个答案:

答案 0 :(得分:1)

您尝试做的事情的一般描述听起来是正确的。

我不会太担心缓冲区的大小;这可能是一些特定的缓冲区。

这是什么Android设备,你试过另一个吗? 4.3或更新的任何Android设备都应该正常运行(较旧的设备因颜色格式值基本上是完全错误,或者在解释YUV数据时需要怪癖而出名),因为CTS测试强制执行正确行为。此测试也与http://bigflake.com/mediacodec/相关联; EncodeDecodeTest.java是相关的。

如果您将该代码连接起来以便可以独立运行它,您可以查看测试是否在您的设备上成功并将其用作参考,以找出代码中的错误,或者得出设备的结论不受信任(您可以忽略它并至少需要4.3,或为其添加特定于设备的解决方法)。