fix: Fix crash in toArrayBuffer() by properly acquiring a reference on AHardwareBuffer* (#2490)

* fix: Fix crash in `toArrayBuffer()` by properly acquiring a reference on `AHardwareBuffer*`

* Format

* Update Podfile.lock
This commit is contained in:
Marc Rousavy 2024-01-31 20:32:02 +01:00 committed by GitHub
parent f896831d4a
commit ae75e22fc0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 7 deletions

View File

@ -15,6 +15,8 @@
#include <android/hardware_buffer.h> #include <android/hardware_buffer.h>
#include <android/hardware_buffer_jni.h> #include <android/hardware_buffer_jni.h>
#include "FinalAction.h"
namespace vision { namespace vision {
using namespace facebook; using namespace facebook;
@ -92,11 +94,13 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr
jsi::HostFunctionType toArrayBuffer = JSI_FUNC { jsi::HostFunctionType toArrayBuffer = JSI_FUNC {
#if __ANDROID_API__ >= 26 #if __ANDROID_API__ >= 26
AHardwareBuffer* hardwareBuffer = this->frame->getHardwareBuffer(); AHardwareBuffer* hardwareBuffer = this->frame->getHardwareBuffer();
AHardwareBuffer_acquire(hardwareBuffer);
finally([&]() { AHardwareBuffer_release(hardwareBuffer); });
AHardwareBuffer_Desc bufferDescription; AHardwareBuffer_Desc bufferDescription;
AHardwareBuffer_describe(hardwareBuffer, &bufferDescription); AHardwareBuffer_describe(hardwareBuffer, &bufferDescription);
__android_log_print(ANDROID_LOG_INFO, "Frame", "Buffer %i x %i @ %i", bufferDescription.width, bufferDescription.height, __android_log_print(ANDROID_LOG_INFO, "Frame", "Converting %i x %i @ %i HardwareBuffer...", bufferDescription.width,
bufferDescription.stride); bufferDescription.height, bufferDescription.stride);
size_t size = bufferDescription.height * bufferDescription.stride; size_t size = bufferDescription.height * bufferDescription.stride;
static constexpr auto ARRAYBUFFER_CACHE_PROP_NAME = "__frameArrayBufferCache"; static constexpr auto ARRAYBUFFER_CACHE_PROP_NAME = "__frameArrayBufferCache";
@ -118,16 +122,21 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr
// Get CPU access to the HardwareBuffer (&buffer is a virtual temporary address) // Get CPU access to the HardwareBuffer (&buffer is a virtual temporary address)
void* buffer; void* buffer;
AHardwareBuffer_lock(hardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_MASK, -1, nullptr, &buffer); int result = AHardwareBuffer_lock(hardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_MASK, -1, nullptr, &buffer);
if (result != 0) {
throw jsi::JSError(runtime, "Failed to lock HardwareBuffer for reading!");
}
finally([&]() {
int result = AHardwareBuffer_unlock(hardwareBuffer, nullptr);
if (result != 0) {
throw jsi::JSError(runtime, "Failed to lock HardwareBuffer for reading!");
}
});
// directly write to C++ JSI ArrayBuffer // directly write to C++ JSI ArrayBuffer
auto destinationBuffer = arrayBuffer.data(runtime); auto destinationBuffer = arrayBuffer.data(runtime);
memcpy(destinationBuffer, buffer, sizeof(uint8_t) * size); memcpy(destinationBuffer, buffer, sizeof(uint8_t) * size);
// Release HardwareBuffer again
AHardwareBuffer_unlock(hardwareBuffer, nullptr);
AHardwareBuffer_release(hardwareBuffer);
return arrayBuffer; return arrayBuffer;
#else #else
throw jsi::JSError(runtime, "Frame.toArrayBuffer() is only available if minSdkVersion is set to 26 or higher!"); throw jsi::JSError(runtime, "Frame.toArrayBuffer() is only available if minSdkVersion is set to 26 or higher!");

34
package/cpp/FinalAction.h Normal file
View File

@ -0,0 +1,34 @@
//
// MutableRawBuffer.h
// VisionCamera
//
// Created by Marc Rousavy on 17.01.24.
// Copyright © 2024 mrousavy. All rights reserved.
//
#pragma once
namespace vision {
template <typename F> struct FinalAction {
public:
FinalAction(F f) : clean_{f} {}
~FinalAction() {
if (enabled_)
clean_();
}
void disable() {
enabled_ = false;
};
private:
F clean_;
bool enabled_ = true;
};
} // namespace vision
template <typename F> vision::FinalAction<F> finally(F f) {
return vision::FinalAction<F>(std::move(f));
}