当前位置: 首页 > 知识库问答 >
问题:

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

郎灿
2023-03-14

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

在从DequeueOutputBuffer()接收到有效的缓冲区索引并获取该ByteBuffer之后,我们将使用GetDirectBufferAddress()从JNI获取C代码中的缓冲区,以便在该端进行转换。但是,由于某些原因,当我们重新看到大小值和字节布局时,所看到的缓冲区似乎没有意义。

根据上次dequeueoutputBuffer()返回mediacodec.info_output_format_changed,我得到的MediaFormat显然是color_formatyUV420semiplanar-下面是完整的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。调试代码时使用的设备是华硕的谷歌Nexus7,运行Android6.0.1。

共有1个答案

贺英悟
2023-03-14

对你要做的事情的一般描述听起来是正确的。

我不会那么担心缓冲区的大小;这可能是某个过度分配的缓冲区。

这是什么Android设备,你有没有试过另一款呢?任何4.3或更高版本的Android设备都应该在这方面表现正确(老版本的都是臭名昭著的错误,颜色格式值基本上是错误的,或者在解释YUV数据时需要一些怪癖),因为有一个CTS测试可以强制执行正确的行为。本测试也链接自http://bigflake.com/mediacodec/;java是相关的。

如果您将代码连接起来,以便可以独立运行它,那么您可以查看测试是否在您的设备上成功,并将其作为参考来找出代码中的错误,或者得出设备不可信的结论(您可以忽略它并要求4.3作为最小值,或者为它添加一个特定于设备的解决方案)。

 类似资料:
  • 默认情况下,通道是不带缓冲区的。 发送端发送数据,同时必须又接收端相应的接收数据。 而带缓冲区的通道则允许发送端的数据发送和接收端的数据获取处于异步状态,就是说发送端发送的数据可以放在缓冲区里面,可以等待接收端去获取数据,而不是立刻需要接收端去获取数据。 不过由于缓冲区的大小是有限的,所以还是必须有接收端来接收数据的,否则缓冲区一满,数据发送端就无法再发送数据了。 package main imp

  • 我试图理解netty缓冲区和水印。 作为一个测试用例,我有一个netty服务器,它向客户端写入数据,客户端被阻塞(每次读取之间的睡眠时间基本上为10秒) > 它是否正在写入操作系统或TCP缓冲区,netty通道是否也有内部缓冲区?如果是这样,我如何配置它? 我跟踪bytesBeforeUnWritable,但它们似乎没有减少 代码如下: 使用端到端源代码重新创建的详细步骤: > 具体来说,代理代码

  • 问题内容: 我是Java的新手。我想做一个游戏。经过大量研究,我不了解缓冲策略的工作原理。.我了解基础知识..它创建了一个屏幕外图像,您以后可以将其放入Windows对象中。 我不知道..我已经研究了很长时间了..根本没有运气..我不知道..也许所有的东西都在里面,而且它很清楚很简单,我我太愚蠢而看不见.. 感谢所有的帮助.. :) 问题答案: 运作方式如下: 该构造了一个当你调用。该知道它属于那

  • 问题内容: 我需要计算从Java非常频繁,是有可能得到本机的版本运行速度比 Java的 的? 我只尝试了jni + C,但是它比纯 java 慢。 问题答案: +1以编写自己的exp()实现。也就是说,如果这 确实 是您应用程序中的瓶颈。如果您可以处理一些不准确性,则可以使用许多非常有效的指数估计算法,其中一些可以追溯到几个世纪以前。据我了解,即使对于必须返回“精确”结果的算法,Java的exp(

  • 问题内容: 当我使用一些线程将数据写入单个文件时遇到问题。 我设置的缓冲区大小,但是无论设置多少,当缓冲区为8192(默认缓冲区大小)而不是我设置的大小(此处为16384)时,它都会将数据刷新到磁盘。我的代码有问题吗? 这就是我构建的方式: 这是完整的代码: 问题答案: 我通过使用OutputStream而不是writer解决了问题,这是代码:

  • 出于性能的考虑,servlet 容器允许(但不要求)缓存输出到客户端的内容。一般的,服务器是默认执行缓存,但应该允许 servlet 来指定缓存参数。 下面是 ServletResponse 接口允许 servlet 来访问和设置缓存信息的方法: getBufferSize setBufferSize isCommitted reset resetBuffer flushBuffer 不管 ser