为什么 JNI GetByteArrayElements 不保留像素步幅
Why JNI GetByteArrayElements does not reserve pixel stride
我需要将 YUV_420_8888 图像从 Android 传递给 C++ 进行处理。所以,我拍摄图像平面,将它们转换为 ByteArray
,然后将它们发送给 C++ 函数。
val yBuffer: ByteBuffer = image.planes[0].buffer
val uBuffer: ByteBuffer = image.planes[1].buffer
val vBuffer: ByteBuffer = image.planes[2].buffer
val yByteArray = ByteArray(yBuffer.remaining())
val uByteArray = ByteArray(uBuffer.remaining())
val vByteArray = ByteArray(vBuffer.remaining())
yBuffer.get(yByteArray)
uBuffer.get(uByteArray)
vBuffer.get(vByteArray)
return NativeCppClass::process(yByteArray, uByteArray, vByteArray)
y
平面的像素步幅为 1。u
和 v
平面的像素步幅为 2。当我查看 uByteArray
和 vByteArray
时,它们正在查看相同的内存块,v
平面在 u
平面之前开始。更具体地说,它们看起来像这样,例如:
vByteArray = [0, 1, 2, 3, 4, 5, 6]
uByteArray = [1, 2, 3, 4, 5, 6, 7]
基于此,我希望我们有以下声明。我们称它为 (*)
以便于参考:
uByteArray.begin - vByteArray.begin = 1; // begin is just a way to express the starting point of a byte array
我还有一个 ByteArray_JNI
可以将 ByteArray
从 Kotlin 转换成一个 class,叫做 CppByteArray
。它们看起来像这样:
class ByteArray_JNI {
public:
using CppType = CppByteArray;
using JniType = jbyteArray;
using Boxed = ByteArray_JNI;
static CppType toCpp(JNIEnv *jniEnv, JniType byteArray) {
return CppType{byteArray, jniEnv};
}
}
class CppByteArray {
public:
CppByteArray(jbyteArray data, JNIEnv *env) : array_(env, data) {
jboolean copied = false;
buffer_ = (uint8_t *)env->GetByteArrayElements(data, &copied);
// copied out param is false at this stage, so no copy
size_ = env->GetArrayLength(data);
}
const uint8_t* data() const {
return buffer_;
}
private:
djinni::GlobalRef<jbyteArray> array_;
uint8_t *buffer_ = nullptr;
jsize size_ = 0;
}
但是,上面的语句 (*)
在 C++ 中是不正确的:
class NativeCppClass {
public:
static CppByteArray process(CppByteArray &&y_array, CppByteArray &&u_array, CppByteArray &&v_array) {
auto u_begin = u_array.data();
auto v_begin = v_array.data();
// u_begin - v_begin = 462848 (not 1 as expected). My image has dimensions 1280x720, just in case it is related to the number 462848.
return something;
}
}
为什么 u_begin - v_begin = 462848
而不是 1? GetByteArrayElements
在这种情况下不执行复制。调用GetByteArrayElements
后输出参数copied
为false。
根据 ByteBuffer 文档:https://developer.android.com/reference/kotlin/java/nio/ByteBuffer#get_2、get
将字节复制到目标数组中。在这种情况下,yByteArray
、uByteArray
和 vByteArray
是从缓冲区复制的。这解释了为什么指针中的偏移量不是 1.
我需要将 YUV_420_8888 图像从 Android 传递给 C++ 进行处理。所以,我拍摄图像平面,将它们转换为 ByteArray
,然后将它们发送给 C++ 函数。
val yBuffer: ByteBuffer = image.planes[0].buffer
val uBuffer: ByteBuffer = image.planes[1].buffer
val vBuffer: ByteBuffer = image.planes[2].buffer
val yByteArray = ByteArray(yBuffer.remaining())
val uByteArray = ByteArray(uBuffer.remaining())
val vByteArray = ByteArray(vBuffer.remaining())
yBuffer.get(yByteArray)
uBuffer.get(uByteArray)
vBuffer.get(vByteArray)
return NativeCppClass::process(yByteArray, uByteArray, vByteArray)
y
平面的像素步幅为 1。u
和 v
平面的像素步幅为 2。当我查看 uByteArray
和 vByteArray
时,它们正在查看相同的内存块,v
平面在 u
平面之前开始。更具体地说,它们看起来像这样,例如:
vByteArray = [0, 1, 2, 3, 4, 5, 6]
uByteArray = [1, 2, 3, 4, 5, 6, 7]
基于此,我希望我们有以下声明。我们称它为 (*)
以便于参考:
uByteArray.begin - vByteArray.begin = 1; // begin is just a way to express the starting point of a byte array
我还有一个 ByteArray_JNI
可以将 ByteArray
从 Kotlin 转换成一个 class,叫做 CppByteArray
。它们看起来像这样:
class ByteArray_JNI {
public:
using CppType = CppByteArray;
using JniType = jbyteArray;
using Boxed = ByteArray_JNI;
static CppType toCpp(JNIEnv *jniEnv, JniType byteArray) {
return CppType{byteArray, jniEnv};
}
}
class CppByteArray {
public:
CppByteArray(jbyteArray data, JNIEnv *env) : array_(env, data) {
jboolean copied = false;
buffer_ = (uint8_t *)env->GetByteArrayElements(data, &copied);
// copied out param is false at this stage, so no copy
size_ = env->GetArrayLength(data);
}
const uint8_t* data() const {
return buffer_;
}
private:
djinni::GlobalRef<jbyteArray> array_;
uint8_t *buffer_ = nullptr;
jsize size_ = 0;
}
但是,上面的语句 (*)
在 C++ 中是不正确的:
class NativeCppClass {
public:
static CppByteArray process(CppByteArray &&y_array, CppByteArray &&u_array, CppByteArray &&v_array) {
auto u_begin = u_array.data();
auto v_begin = v_array.data();
// u_begin - v_begin = 462848 (not 1 as expected). My image has dimensions 1280x720, just in case it is related to the number 462848.
return something;
}
}
为什么 u_begin - v_begin = 462848
而不是 1? GetByteArrayElements
在这种情况下不执行复制。调用GetByteArrayElements
后输出参数copied
为false。
根据 ByteBuffer 文档:https://developer.android.com/reference/kotlin/java/nio/ByteBuffer#get_2、get
将字节复制到目标数组中。在这种情况下,yByteArray
、uByteArray
和 vByteArray
是从缓冲区复制的。这解释了为什么指针中的偏移量不是 1.