Android метод NDK имеет проблему с повторным входом

Это мой метод NDK:

 void FrameReceived(int width, int height, const char *rawImageBytes, int size, jboolean remote)
{
//LOGE(".... **** ....FrameReceived Begin = %d", size);

if(size == 0)
    return;

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

env = getJniEnv(&isAttached);

if (env == NULL)
    goto FAIL0;
//LOGE(".... **** ....TRYING TO FIND CALLBACK");
LOGI("FrameReceived will reach here 1");
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
}

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;

jRawImageBytes = (*env)->NewByteArray(env, size);
(*env)->SetByteArrayRegion(env, jRawImageBytes, 0, size, modifiedRawImageBytes);

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

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

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

Какие вызовы, основанные на удаленном jboolean, 1 из этих 2 функций:

 public void vidyoConferenceFrameReceivedCallback(final int participantId, final int width, final int height, final byte[] rawImageBytes) {
    if (selfView == null || selfView.getVisibility() == View.GONE)
        return;
    try {
        selfBitmap = Nv21Image.nv21ToBitmap(rs, rawImageBytes, width, height);
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                selfView.setImageBitmap(selfBitmap);
            }
        });
    } catch (Exception e) {
        Logger.error("Error on vidyoConferenceFrameReceivedCallback: " + e.getMessage());
    }
}

И этот:

public void vidyoConferenceFrameReceivedRemoteCallback(final int participantId, final int width, final int height, final byte[] rawImageBytes) {
    if (remoteView == null || remoteView.getVisibility() == View.GONE)
        return;
    try {
        remoteResolution = width + "x" + height;
        remoteBitmap = Nv21Image.nv21ToBitmap(rs, rawImageBytes, width, height);
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                remoteView.setImageBitmap(remoteBitmap);
            }
        });
    } catch (Exception e) {
        Logger.error("Error on vidyoConferenceFrameReceivedRemoteCallback: " + e.getMessage());
    }
}

Как видите, эти две функции выглядят одинаково, различаются только изображение и растровое изображение, в котором я сохраняю данные. но если я профилирую свое приложение.

Первый метод, когда он вызывается, его поток выглядит следующим образом: >https://s3.amazonaws.com/uploads.hipchat.com/39260/829560/A3lm3QTz4gZN0VK/upload.png И это среднее время составляет 4 секунды для 15 секунд профилирования.

НО второй метод, удаленный, делает следующее: https://s3.amazonaws.com/uploads.hipchat.com/39260/829560/wHp7NtKgKYTTEG7/upload.png И время 15 секунд из 15.

Здесь вы можете ясно видеть, что каким-то образом это избыточно вспоминается: >https://s3.amazonaws.com/uploads.hipchat.com/39260/829560/wCmS5CH21zbyMBr/upload.png

Почему это происходит?

Редактировать:

Я изменил удаленную функцию, чтобы просто сделать это:

public void vidyoConferenceFrameReceivedRemoteCallback(final int participantId, final int width, final int height, final byte[] rawImageBytes) {
    Log.i("", "vidyoConferenceFrameReceivedRemoteCallback RECEIVED FRAME ");
}

И, профилируя эту ветку, я получаю следующее: https://s3.amazonaws.com/uploads.hipchat.com/39260/829560/ZfylnBheyA6GjTe/upload.png

Я думаю, что что-то в NDK заставляет функцию вызываться несколько раз.


person rosu alin    schedule 30.04.2018    source источник
comment
ну, одно различие может заключаться в том, что разрешение видео не совпадает для selfView и remoteView. Обратите внимание, что я предупреждал вас, что setImageBitmap () слишком медленно для живого видео.   -  person Alex Cohn    schedule 01.05.2018
comment
Это правда, но по какой-то причине я получаю от рендерскрипта лучшую производительность, чем от моего кода openGL. и я профилировал оба, и для обоих я получаю удаленный код, вызываемый 4 раза вместо одного. PS: разрешение меньше, чем у селфи   -  person rosu alin    schedule 01.05.2018
comment
Первый вопрос, который я хотел бы задать, это почему показано, что yuvToRgb вызывает сам себя.   -  person Alex Cohn    schedule 01.05.2018
comment
Вот и я тоже потерялся. Я редактирую свой вопрос сейчас, чтобы включить больше данных   -  person rosu alin    schedule 01.05.2018
comment
Ваша интерпретация результатов профайлера неверна. Конечно, обратный вызов запускается для каждого полученного кадра, но профилировщик показывает только методы Java.   -  person Alex Cohn    schedule 01.05.2018
comment
Я добавил несколько журналов в код NDK, и он не вызывается с большей скоростью, чем vidyoConferenceFrameReceivedCallback. Но я не понимаю, даже для журнала внутри моей функции, почему он вызывается несколько раз. Кроме того, каков код, относящийся к ThreadGroup и Refference, то есть то, что вызывается из NDK, как я предполагаю?   -  person rosu alin    schedule 01.05.2018
comment
Давайте продолжим это обсуждение в чате.   -  person Alex Cohn    schedule 01.05.2018