[BUG] Android: TargetRawDataOutput work wrong
lambiengcode opened this issue · 3 comments
Describe the bug
Only 0 and 255 in callback data, When I convert it to Bitmap, only black frame.
How To Reproduce the bug
Using TargetRawDataOutput instead of GPUPixelView in example project
Expected behavior
When I put the similar log for iOS or macOS it response multiple value between 0 and 255, but in android, just 0 and 255
Screenshots
If applicable, add screenshots to help explain your problem.
Running Information(please complete the following information):
- GPUPixel Version using : 1.2.5
- Operating System: Android 14 - HyperOS
- Device Info: Xiaomi 11T 5G
Additional context
I write 2 function in JNI:
std::list<std::shared_ptr<Filter>> filter_list_;
std::shared_ptr<SourceRawDataInput> gpuPixelRawInput;
std::shared_ptr<BeautyFaceFilter> beauty_face_filter_;
std::shared_ptr<TargetRawDataOutput> targetRawOutput_;
std::shared_ptr<FaceReshapeFilter> face_reshape_filter_;
std::shared_ptr<gpupixel::FaceMakeupFilter> lipstick_filter_;
std::shared_ptr<gpupixel::FaceMakeupFilter> blusher_filter_;
static const char* TAG = "FlutterRTCBeautyFilters";
extern "C" JNIEXPORT void JNICALL
Java_com_pixpark_gpupixel_GPUPixel_nativeInitSourceRawDataInput(JNIEnv* env, jclass, jobject source) {
jobject globalSourceRef = env->NewGlobalRef(source);
jclass cls = env->GetObjectClass(globalSourceRef);
jmethodID mid = env->GetMethodID(cls, "onRawOutput", "([BII)V");
if (!mid) return;
gpuPixelRawInput = SourceRawDataInput::create();
// Create filters
lipstick_filter_ = LipstickFilter::create();
blusher_filter_ = BlusherFilter::create();
face_reshape_filter_ = FaceReshapeFilter::create();
gpuPixelRawInput->RegLandmarkCallback([=](std::vector<float> landmarks) {
lipstick_filter_->SetFaceLandmarks(landmarks);
blusher_filter_->SetFaceLandmarks(landmarks);
face_reshape_filter_->SetFaceLandmarks(landmarks);
});
targetRawOutput_ = TargetRawDataOutput::create();
beauty_face_filter_ = BeautyFaceFilter::create();
gpuPixelRawInput->setRotation(RotationMode::NoRotation);
lipstick_filter_->setBlendLevel(0.1f);
blusher_filter_->setBlendLevel(0.2f);
face_reshape_filter_->setFaceSlimLevel(0.1f);
face_reshape_filter_->setEyeZoomLevel(0.1f);
beauty_face_filter_->setWhite(0.2f);
JavaVM* jvm;
env->GetJavaVM(&jvm);
targetRawOutput_->setPixelsCallbck([jvm, globalSourceRef, mid](const uint8_t* data, int width, int height, int64_t ts) {
__android_log_print(ANDROID_LOG_INFO, TAG, "Received output with height: %d, width: %d", height, width);
JNIEnv* myNewEnv;
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6;
args.name = NULL;
args.group = NULL;
jvm->AttachCurrentThread(reinterpret_cast<JNIEnv **>((void **) &myNewEnv), &args);
for (int i = 0; i < width * height; i++) {
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Data[%d]: %d", i, data[i]);
}
size_t rgba_size = width * height * 4;
uint8_t* argbData = (uint8_t*)malloc(rgba_size);
// Convert RGBA to ARGB
for (int i = 0; i < width * height; ++i) {
argbData[i * 4 + 0] = data[i * 4 + 3]; // Alpha
argbData[i * 4 + 1] = data[i * 4 + 0]; // Red
argbData[i * 4 + 2] = data[i * 4 + 1]; // Green
argbData[i * 4 + 3] = data[i * 4 + 2]; // Blue
}
jbyte* argb_byte = (jbyte*)argbData;
jbyteArray jARGB = myNewEnv->NewByteArray(rgba_size);
myNewEnv->SetByteArrayRegion(jARGB, 0, rgba_size, argb_byte);
myNewEnv->CallVoidMethod(globalSourceRef, mid, jARGB, width, height);
myNewEnv->DeleteLocalRef(jARGB);
});
gpuPixelRawInput->addTarget(lipstick_filter_)
->addTarget(blusher_filter_)
->addTarget(face_reshape_filter_)
->addTarget(beauty_face_filter_)
->addTarget(targetRawOutput_);
}
extern "C" void Java_com_pixpark_gpupixel_GPUPixel_nativeWaterbusUploadBytes(
JNIEnv* env,
jclass,
jintArray jPixel,
jint width,
jint height,
jint stride
) {
int64_t ts = Util::nowTimeMs();
jint* pixels = env->GetIntArrayElements(jPixel, 0);
gpuPixelRawInput->uploadBytes((uint8_t*)pixels, width, height, stride, ts);
env->ReleaseIntArrayElements(jPixel, pixels, 0);
}
I referred to your jni code, and an opengl error occured when I ran the app."call to OpenGL ES API with no current context (logged once per thread)" How can I solve it?
I referred to your jni code, and an opengl error occured when I ran the app."call to OpenGL ES API with no current context (logged once per thread)" How can I solve it?
Managed to solve the gl thread error, and got correct output data with your Jni code, on XiaoMi9
A small problem: You used uint8_t* argbData = (uint8_t*)malloc(rgba_size); to allocate memory for the output data, and did not destroy it after using it, which results in a memory leak.