簡體   English   中英

將無符號char *從C ++作為字節[]傳遞給Java的最有效方法

[英]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);
        }
    }

這里的encodedDatabyte[] ,它是使用一次內存分配並每次執行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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM