[英]Most efficient way to pass unsigned char* from C++ to java as byte[]
我有一个本机功能,签名就像-
void onRecvData(const unsigned char* pData, int length)
我需要将此pData
从C ++传递到Java方法public void OnrecvData(byte[] data)
而无需复制数据。 目前,我正在通过分配jByteBuffer
并使用SetByteArrayRegion
做到这SetByteArrayRegion
。 但是我认为这种方法无法避免复制。 我正在寻找一种类似GetDirectBufferAddress
,并将指针传递给起始地址和长度以避免复制。
提前致谢!
编辑1
我不会在Java层中修改数据。 只读访问将可以。
编辑2
您可以dequeueInputBuffer(),将该缓冲区传递到本机代码中,并memcpy()数据。 我99%肯定MediaCodec缓冲区是直接的ByteBuffer,因此您可以使用JNI函数获取地址和长度。 如何调用dequeueInputBuffer()由您决定。 您必须使用MediaCodec返回的缓冲区,因此不可避免地需要一个副本,但至少它是编码数据。 (出于多种原因,对于输出端,您希望使用Surface。)
我当前的代码是这样的-
// ..................
// ..................
int inIndex = mMediaCodec.dequeueInputBuffer(mTimeoutUs);
if (inIndex >= 0) {
ByteBuffer buffer;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
buffer = mMediaCodec.getInputBuffers()[inIndex];
buffer.clear();
} else {
buffer = mMediaCodec.getInputBuffer(inIndex);
}
if (buffer != null) {
buffer.put(encodedData, 0, encodedDataLength);
long presentationTimeUs = System.nanoTime() / 1000l;
mMediaCodec.queueInputBuffer(inIndex, 0, encodedDataLength, presentationTimeUs, 0);
}
}
这里的encodedData
是byte[]
,它是使用一次内存分配并每次执行SetByteArrayRegion
从本机层SetByteArrayRegion
unsigned char*
接收的。 因此,我需要像我建议的memcpy
方法那样在当前的实现中使用一个副本。 这两种方法都需要一个副本,但是我当前的实现是否比您建议的效率低(发送dequeueInputBuffer
地址参考和memcpy
)? 像put
ING byte[]
到ByteBuffer
我在Java中没有层?
编辑3
好吧, ByteBuffer.put(byte[], offset, offsetLength)
就像将整个byte[]
数组像memcpy
一样复制到ByteBuffer
。 因此它也是Java层中的另一个副本。 我现在要实现你的想法。 谢谢 :)
这个问题比看起来要复杂得多。
使数据在Java语言代码中可见的最快方法是预分配“直接” ByteBuffer,然后在其中接收数据。 可以直接从本机或托管代码访问数据。 但是,“可访问”只是意味着Java语言代码可以实现它,而不是它可以快速获取单个字节。
如果从JNI(使用NewDirectByteBuffer
)分配直接ByteBuffer,则可以NewDirectByteBuffer
传递任意缓冲区,但这意味着没有byte[]
支持存储。 如果您使用ByteBuffer#allocateDirect()
从托管代码中分配它,则最新版本的Android将为您提供直接缓冲区,该缓冲区位于托管堆中,这意味着也可以通过array()
对其进行访问。 这样,用Java编写的代码就可以像访问任何其他byte[]
一样访问它,而不必每次访问都调用一个方法。
如果您的数据到达了您无法控制的缓冲区(例如,视频解码器输出),那么您就别无选择。 您要么将数据复制到托管byte[]
,要么在Java端支付每字节的开销。 (理论上,JIT可以识别您在做什么并对其进行优化,但是我不知道这是否正在完成。)
尽量避免分配缓冲区。 预分配和池化可以帮助您提高性能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.