opencv_processor.cpp 1.9 KB
#include <jni.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>

using namespace cv;

extern "C" JNIEXPORT jobjectArray JNICALL
Java_io_livekit_android_room_track_video_OpenCVVideoProcessor_processI420(
    JNIEnv *env,
    jobject thiz,
    jbyteArray y,
    jbyteArray u,
    jbyteArray v,
    jint width,
    jint height,
    jint rotation,
    jlong timestamp) {

    jbyte* yPtr = env->GetByteArrayElements(y, NULL);
    jbyte* uPtr = env->GetByteArrayElements(u, NULL);
    jbyte* vPtr = env->GetByteArrayElements(v, NULL);

    Mat yuvMat(height + height / 2, width, CV_8UC1);
    memcpy(yuvMat.data, yPtr, height * width);
    memcpy(yuvMat.data + height * width, uPtr, (height / 2) * (width / 2));
    memcpy(yuvMat.data + height * width + (height / 2) * (width / 2), vPtr, (height / 2) * (width / 2));

    Mat rgbMat;
    cvtColor(yuvMat, rgbMat, COLOR_YUV2RGB_I420);

    Mat grayMat;
    cvtColor(rgbMat, grayMat, COLOR_RGB2GRAY);
    cvtColor(grayMat, rgbMat, COLOR_GRAY2RGB);

    Mat newYuvMat;
    cvtColor(rgbMat, newYuvMat, COLOR_RGB2YUV_I420);

    int ySize = height * width;
    int uvSize = (height / 2) * (width / 2);

    jbyteArray newY = env->NewByteArray(ySize);
    env->SetByteArrayRegion(newY, 0, ySize, (jbyte*)newYuvMat.data);

    jbyteArray newU = env->NewByteArray(uvSize);
    env->SetByteArrayRegion(newU, 0, uvSize, (jbyte*)(newYuvMat.data + ySize));

    jbyteArray newV = env->NewByteArray(uvSize);
    env->SetByteArrayRegion(newV, 0, uvSize, (jbyte*)(newYuvMat.data + ySize + uvSize));

    jclass byteArrayClass = env->FindClass("[B");
    jobjectArray result = env->NewObjectArray(3, byteArrayClass, NULL);
    env->SetObjectArrayElement(result, 0, newY);
    env->SetObjectArrayElement(result, 1, newU);
    env->SetObjectArrayElement(result, 2, newV);

    env->ReleaseByteArrayElements(y, yPtr, 0);
    env->ReleaseByteArrayElements(u, uPtr, 0);
    env->ReleaseByteArrayElements(v, vPtr, 0);

    return result;
}