当前位置: 首页 > 知识库问答 >
问题:

我正在尝试修改一个字节数组并通过JNI将其从c发送到java

谭高峯
2023-03-14

这是我的职能:

void FrameReceived(int width, int height, const char *rawImageBytes, int size, jboolean remote)
{

if(size == 0)
    return;

jboolean isAttached;
JNIEnv *env;
jint jParticipant;
jint jWidth;
jint jHeight;
jbyte *jRawImageBytes;
jbyte *modifiedRawImageBytes;
jbyteArray Array;

env = getJniEnv(&isAttached);

if (env == NULL)
    goto FAIL0;
//LOGE(".... **** ....TRYING TO FIND CALLBACK");
if(remote)
{
    if(frameReceivedRemoteMethod == NULL)
        frameReceivedRemoteMethod = getApplicationJniMethodId(env, applicationJniObj, "vidyoConferenceFrameReceivedRemoteCallback", "(III[B)V");

    if (frameReceivedRemoteMethod == NULL) {
        //LOGE(".... **** ....CALLBACK NOT FOUND");
        goto FAIL1;
    }
}
else
{
    if(frameReceivedMethod == NULL)
        frameReceivedMethod = getApplicationJniMethodId(env, applicationJniObj, "vidyoConferenceFrameReceivedCallback", "(III[B)V");

    if (frameReceivedMethod == NULL) {
        //LOGE(".... **** ....CALLBACK NOT FOUND");
        goto FAIL1;
    }
}

jWidth = width;
jHeight = height;
LOGI("FrameReceived will reach here 1");

jRawImageBytes = (*env)->NewByteArray(env, size);
LOGI("FrameReceived will reach here 2");
(*env)->SetByteArrayRegion(env, jRawImageBytes, 0, size, rawImageBytes);
LOGI("FrameReceived will reach here 3");
//TODO will transform to NV21 in ndk (faster)
modifiedRawImageBytes = (*env)->NewByteArray(env, size);
LOGI("FrameReceived will reach here 4");
jint sizeWH = width * height;
jint quarter = sizeWH/4;
jint v0 = sizeWH + quarter;
LOGI("FrameReceived will reach here 5");
for (int u = sizeWH, v = v0, o = sizeWH; u < v0; u++, v++, o += 2) {
    modifiedRawImageBytes[o] = jRawImageBytes[v]; // For NV21, V first
    modifiedRawImageBytes[o + 1] = jRawImageBytes[u]; // For NV21, U second
}
LOGI("FrameReceived will reach here 6");
(*env)->SetByteArrayRegion(env, Array, 0, size, modifiedRawImageBytes);
LOGI("FrameReceived will reach here 7");

//LOGE(".... **** ....CALLBACK BEING CALLED");
if(remote)
{
    (*env)->CallVoidMethod(env, applicationJniObj, frameReceivedRemoteMethod, 0, jWidth, jHeight, Array);
}
else
{
    (*env)->CallVoidMethod(env, applicationJniObj, frameReceivedMethod, 0, jWidth, jHeight, Array);
}
//LOGE(".... **** ....CALLBACK CALLED");

(*env)->DeleteLocalRef(env, jRawImageBytes);

if (isAttached)
{
    (*global_vm)->DetachCurrentThread(global_vm);
}
//LOGE("FrameReceived End");
return;
FAIL1:
if (isAttached)
{
    (*global_vm)->DetachCurrentThread(global_vm);
}
FAIL0:
//LOGE("FrameReceived FAILED");
return;
}

并且它总是在这个LOG:LOGI之后崩溃(“FrameReceived将到达这里5”)。我在这里做错了什么?这就是我试图在NDK中实现的目标:

public byte[]i420 tonv 21(final byte[]input,byte[] output,final int width,final int height){ if(output = = null){ output = new byte[input . length];} final int size = width * heightfinal int quarter = size/4;final int v0 = size quarter

    System.arraycopy(input, 0, output, 0, size); // Y is same

    for (int u = size, v = v0, o = size; u < v0; u++, v++, o += 2) {
        output[o] = input[v]; // For NV21, V first
        output[o + 1] = input[u]; // For NV21, U second
    }
    return output;
}

所以我可以将corect格式字节数组发送到java。并且不必在我的java代码中执行此方法。为什么它不能将for循环中的值添加到字节数组中?

共有1个答案

柯耀
2023-03-14

所以为了做到这一点,我改变了一点逻辑。有char*rawImageBytes,它的大小。而不是直接创建一个jbyteArray。我将为另一个char数组分配空间。我将从第一个复制内存,在第二个。然后我调用for循环,以便修改我需要的东西,只有在那之后,我才会创建jbyteArray:

char *modifiedRawImageBytes = malloc(size);
memcpy(modifiedRawImageBytes, rawImageBytes, size);
jint sizeWH = width * height;
jint quarter = sizeWH/4;
jint v0 = sizeWH + quarter;
for (int u = sizeWH, v = v0, o = sizeWH; u < v0; u++, v++, o += 2) {
        modifiedRawImageBytes[o] = rawImageBytes[v]; // For NV21, V first
        modifiedRawImageBytes[o + 1] = rawImageBytes[u]; // For NV21, U second
}
jWidth = width;
jHeight = height;

jRawImageBytes = (*env)->NewByteArray(env, size);
(*env)->SetByteArrayRegion(env, jRawImageBytes, 0, size, modifiedRawImageBytes);
 类似资料:
  • 问题内容: 我正在构建Android应用程序的项目的C 方面。我需要一些信息(通过字符串和字符串数组)传递给Java应用程序(通过JNI)。我以前从未做过,相反方向的人没有C 的经验,并承认他们不能真正提供帮助。 我确实找到了以下代码(从这里开始) 但这对我来说毫无意义。通常,我不确定如何将其合并到程序的C ++端,而且我无法确切了解其工作原理。代码是否在执行该行时发出消息?还是在for循环中执行

  • 我目前正在学习网络,需要一些帮助来找出通过UDP从Java程序向C程序发送字节数组的最简单方法。以前,我用java创建了一个非常简单的客户机和服务器程序,并且能够使用Java类DatagramSocket和DatagramPacket在两个Java客户机/服务器程序之间发送和接收数据包。 但是现在,我有一个网络仿真器,我需要通过它,它是用C编写的,所以我担心它无法识别DatagramSocket和

  • 因此,我创建了我的对象数组,每个对象都被初始化为一个新字节[1024]: 然后,我遍历这个数组中的所有索引,执行如下操作: 在大多数情况下,一切都很好。但是,如果我希望每个字节数组都是可变长度的呢?也就是说,我希望字节数组的数组是“锯齿状”的。我将什么作为最后一个参数传递给NewObjectArray()作为初始值?我尝试传递0作为初始值,以防止在创建jobjectArray时进行初始化,然后分配

  • 我有一个关于在Android中发送字节数组的问题。 我以前试图使用Android httpclient文件上传数据损坏和超时问题 但是,我真的不知道如何使用它。。。。。。 在我的项目中,我之前使用NameValuePair列表将String类型的数据发送到Apache服务器,例如 在 post 方法中(DB_Packet是字符串变量) list name value pair = new Arra

  • 问题内容: 我的Java应用程序使用JNI调用用C编写的库。此本地库将错误记录到stderr,但是我想以某种方式通过我的log4j记录器重定向错误流。这可能吗? C库是外部的-我没有源,所以无法更改它。 谢谢 问题答案: 注意:我尚未尝试此答案;YMMV。 POSIX方法将更改与流关联的基础文件。如联机帮助页所述:“ freopen()函数的主要用途是更改与标准文本流(stderr,stdin或s

  • 问题内容: 我正在使用ajax提交包含数组,文本字段和文件的多部分表单。 我将每个VAR附加到主数据中 然后我使用ajax函数将其发送到PHP文件以存储在sql DB中。 但是在PHP方面,变量(即数组)显示为字符串。 当我不使用ajax作为表单数据发送它,而是使用简单的选项时,确实在PHP端将它作为数组获得,但是后来我也无法发送文件。 有什么办法吗? 问题答案: 您有几种选择: 将其转换为JSO