[英]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.