Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I need to pass a YUV_420_8888 image from Android to C++ for processing. So, I take the image planes, convert them to
ByteArray
, then send them to C++ function.
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
plane has pixel stride 1. u
and v
planes have pixel stride 2. When I look at uByteArray
and vByteArray
, they are viewing the same memory block, with v
plane starts before u
plane. More particular, they look like this, for example:
vByteArray = [0, 1, 2, 3, 4, 5, 6]
uByteArray = [1, 2, 3, 4, 5, 6, 7]
Based on this, I expect we have this statement below. Let's call it (*)
for easier reference:
uByteArray.begin - vByteArray.begin = 1; // begin is just a way to express the starting point of a byte array
I also have a ByteArray_JNI
to convert ByteArray
from Kotlin into a class called CppByteArray
. They look like this:
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;
However, statement (*)
above is not true inside 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;
Why u_begin - v_begin = 462848
but not 1? GetByteArrayElements
does not perform a copy in this case. The output parameter copied
is false after calling GetByteArrayElements
.
–
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.